OpencvForUnity学习:六:识别手指的最高点

目录

一、目的:找到手指的最高点

一、参考:

1、参考我之前写的OpenCVForUnity文章,一步步走来不容易,里面好多的函数名字和Opencv不一样,并且OpenCVForUnity文档都没有解释,只能自己瞎琢磨

一、过程

1、复制OpenCVForUnity中HandPoseEstimationExample案例

1、自己新建代码,让RawImage显示相机画面

1、My_test10_findHandHighestPoint

①将HandPoseEstimationExample代码里面的Update删除掉,一些没有用到的删除掉,然后写上自己的代码,主要是Test_hsv06函数

1、My_test10_WebCamTextureToMatHelper

①主要是复制一下WebCamTextureToMatHelperExample代码,改一下内部名字为My_test10_WebCamTextureToMatHelper就可以了,其他没有动,目的为了只修改My_test10_WebCamTextureToMatHelper代码不动它原本代码

1、效果:Cube随着手指最高点移动


一、目的:找到手指的最高点

一、参考:

1、参考我之前写的OpenCVForUnity文章,一步步走来不容易,里面好多的函数名字和Opencv不一样,并且OpenCVForUnity文档都没有解释,只能自己瞎琢磨

一、过程

1、复制OpenCVForUnity中HandPoseEstimationExample案例

1、自己新建代码,让RawImage显示相机画面

1、My_test10_findHandHighestPoint

①将HandPoseEstimationExample代码里面的Update删除掉,一些没有用到的删除掉,然后写上自己的代码,主要是Test_hsv06函数

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;

using OpenCVForUnity.CoreModule;
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.UnityUtils.Helper;
using OpenCVForUnity.UnityUtils;

using OpenCVForUnity.ImgcodecsModule;



namespace OpenCVForUnityExample
{
    /// <summary>
    /// Hand Pose Estimation Example
    /// Referring to https://www.youtube.com/watch?v=KuGpOxOcpds.
    /// </summary>
    //[RequireComponent (typeof(WebCamTextureToMatHelper))]//案例中的代码进行注释修改为自己的
    [RequireComponent(typeof(My_test10_WebCamTextureToMatHelper))]

    /// <summary>
    /// 成功:找到手的最高点
    /// 复制My_test10_findHand(里面写了很多的手指最高点的测试代码)然后进行新的操作
    /// </summary>

    public class My_test10_findHandHighestPoint : MonoBehaviour
    {
        /// <summary>显示webCamTexture画面的</summary>
        public GameObject obj_showWebCam;

        /// <summary>The gray mat.</summary>
        private Mat grayMat;

        /// <summary>蝴蝶飞行的目的地</summary>
        public GameObject obj_butterflyTarget;       


        /// <summary>
        /// The number of fingers text.
        /// </summary>
        public UnityEngine.UI.Text numberOfFingersText;

        /// <summary>
        /// The threashold slider.
        /// </summary>
        public Slider threasholdSlider;

        /// <summary>
        /// The texture.
        /// </summary>
        Texture2D texture;

        /// <summary>
        /// The BLOB color hsv.
        /// </summary>
        Scalar blobColorHsv;

        / <summary>
        / The BLOB color rgba.
        / </summary>
        //Scalar blobColorRgba;

        /// <summary>
        /// The detector.
        /// </summary>
        ColorBlobDetector detector;

        /// <summary>
        /// The spectrum mat.
        /// </summary>
        Mat spectrumMat;

        /// <summary>
        /// Indicates whether is color selected.
        /// </summary>
        bool isColorSelected = false;

        /// <summary>
        /// The spectrum size.
        /// </summary>
        Size SPECTRUM_SIZE;

        /// <summary>
        /// The contour color.
        /// </summary>
        Scalar CONTOUR_COLOR;

        /// <summary>
        /// The contour color white.
        /// </summary>
        Scalar CONTOUR_COLOR_WHITE;

        /// <summary>
        /// The number of fingers.
        /// </summary>
        int numberOfFingers = 0;

        /// <summary>
        /// The webcam texture to mat helper.
        /// </summary>
     //   WebCamTextureToMatHelper webCamTextureToMatHelper;  //案例中的代码进行注释修改为自己的
        My_test10_WebCamTextureToMatHelper webCamTextureToMatHelper;

        /// <summary>
        /// The stored touch point.
        /// </summary>
        Point storedTouchPoint;

        /// <summary>
        /// The FPS monitor.
        /// </summary>
        FpsMonitor fpsMonitor;

        // Use this for initialization
        void Start()
        {
            fpsMonitor = GetComponent<FpsMonitor>();

            //webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper> ();  //案例中的代码进行注释修改为自己的
            webCamTextureToMatHelper = gameObject.GetComponent<My_test10_WebCamTextureToMatHelper>();

#if UNITY_ANDROID && !UNITY_EDITOR
            // Avoids the front camera low light issue that occurs in only some Android devices (e.g. Google Pixel, Pixel2).
            webCamTextureToMatHelper.avoidAndroidFrontCameraLowLightIssue = true;
#endif
            webCamTextureToMatHelper.Initialize();

        }

        /// <summary>
        /// Raises the web cam texture to mat helper initialized event.
        /// </summary>
        public void OnWebCamTextureToMatHelperInitialized()
        {
            Debug.Log("OnWebCamTextureToMatHelperInitialized");

            Mat webCamTextureMat = webCamTextureToMatHelper.GetMat();

            texture = new Texture2D(webCamTextureMat.cols(), webCamTextureMat.rows(), TextureFormat.RGBA32, false);

            //案例中的代码进行注释修改为自己的
            //gameObject.GetComponent<Renderer> ().material.mainTexture = texture;

            //案例中的代码进行注释修改为自己的
            //gameObject.transform.localScale = new Vector3 (webCamTextureMat.cols (), webCamTextureMat.rows (), 1);

            //成功:摄像头画面在RawImage显示
            obj_showWebCam.GetComponent<RawImage>().texture = texture;
            
            Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);

            if (fpsMonitor != null) {
                fpsMonitor.Add("width", webCamTextureMat.width().ToString());
                fpsMonitor.Add("height", webCamTextureMat.height().ToString());
                fpsMonitor.Add("orientation", Screen.orientation.ToString());
                fpsMonitor.consoleText = "Please touch the area of the open hand.";
            }


            float width = webCamTextureMat.width();
            float height = webCamTextureMat.height();

            float widthScale = (float)Screen.width / width;
            float heightScale = (float)Screen.height / height;
            if (widthScale < heightScale) {
                Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
            } else {
                Camera.main.orthographicSize = height / 2;
            }

            detector = new ColorBlobDetector();
            spectrumMat = new Mat();
            //blobColorRgba = new Scalar (255);
            blobColorHsv = new Scalar(255);
            SPECTRUM_SIZE = new Size(200, 64);
            CONTOUR_COLOR = new Scalar(255, 0, 0, 255);
            CONTOUR_COLOR_WHITE = new Scalar(255, 255, 255, 255);
        }

        /// <summary>
        /// Raises the web cam texture to mat helper disposed event.将web cam纹理提升到mat助手处理事件。
        /// </summary>
        public void OnWebCamTextureToMatHelperDisposed()
        {
            Debug.Log("OnWebCamTextureToMatHelperDisposed");

            if (spectrumMat != null)
            {
                spectrumMat.Dispose();
                spectrumMat = null;
            }
            if (texture != null)
            {
                Texture2D.Destroy(texture);
                texture = null;
            }

            if (grayMat != null)
            {
                grayMat.Dispose();
            }

            //grayPixels = null;

        }

        / <summary>
        / Raises the web cam texture to mat helper error occurred event.
        / </summary>
        / <param name="errorCode">Error code.</param>
        //public void OnWebCamTextureToMatHelperErrorOccurred (WebCamTextureToMatHelper.ErrorCode errorCode)
        //{
        //    Debug.Log ("OnWebCamTextureToMatHelperErrorOccurred " + errorCode);
        //}

        /// <summary>
        /// Raises the web cam texture to mat helper error occurred event.
        /// </summary>
        /// <param name="errorCode">Error code.</param>
        public void OnWebCamTextureToMatHelperErrorOccurred(My_test10_WebCamTextureToMatHelper.ErrorCode errorCode)
        {
            Debug.Log("OnWebCamTextureToMatHelperErrorOccurred " + errorCode);
        }

        //测试:修改为点击UI中识别手势
        // Update is called once per frame
        void Update()
        {
            Test_hsv06();            
        }        

        /// <summary>
        ///测试:目的:找到了最高点后,让某个物体跟着这个最高点移动,这样方便蝴蝶有飞行的目标点
        /// </summary>
        private void Test_hsv06()
        {
            //第一步:找到摄像头的Mat
            Mat tmp_rgbaMat = webCamTextureToMatHelper.GetMat();
            if (tmp_rgbaMat == null)
                return;

            //  第二步:自己定义肤色的hsv的颜色(可能后期需要设置多个肤色HSV)
            Scalar tmp_blobColorHsv = new Scalar(255);
            tmp_blobColorHsv.val[0] = 8.4;
            tmp_blobColorHsv.val[1] = 75;
            tmp_blobColorHsv.val[2] = 165;

            //  第三步:ColorBlobDetector设置二进制匹配,将需要匹配的肤色的scalar传递进去
            ColorBlobDetector tmp_detector = new ColorBlobDetector();
            tmp_detector.SetHsvColor(tmp_blobColorHsv);

            //第四步:得到满足肤色的二进制匹配对象的轮廓,并且将其绘制出来
            //已经找到了hsv,然后将视频中hsv的地方全部绘制轮廓,并且找到最高点;模拟:HandPoseEstimationExample案例的HandPoseEstimationProcess代码
            Imgproc.GaussianBlur(tmp_rgbaMat, tmp_rgbaMat, new Size(3, 3), 1, 1);
            List<MatOfPoint> tmp_contours = tmp_detector.GetContours();
            tmp_detector.Process(tmp_rgbaMat);//将设置了HSV的图片给摄像头mat
            if (tmp_detector != null)
                tmp_detector.Dispose();

            if (tmp_contours.Count <= 0)
                return;

            //成功:描绘出定义HSV颜色的轮廓:
            Scalar tmp_CONTOUR_COLOR = new Scalar(17, 255, 58, 255);//描绘的颜色
            Imgproc.drawContours(tmp_rgbaMat, tmp_contours, 1, tmp_CONTOUR_COLOR, 10);
            //print("tmp_contours.Count:" + tmp_contours.Count);
            //print("tmp_contours:" + tmp_contours);

            //第五步:将满足肤色二进制匹配对象轮廓的最高点绘制出来
            //成功:找到轮廓的最高点,并且将其描绘出来;参考:ConvexHullExample案例
            //运行效果发现,使用数组第一个很符合最高点的要求,所以没有进行最高点的判断了,
            Point[] array_pt = tmp_contours[0].toArray();
            for (int i = 0; i < array_pt.Length; ++i)
            {
                Imgproc.circle(tmp_rgbaMat, array_pt[0], 2, new Scalar(255, 255, 255), 100);//画出随机点
               
            }

            //第六步:找到了最高点后,让蝴蝶飞行的目标点跟着这个最高点移动
            //成功:找到Mat中符合指定hsv像素的坐标占据Mat的比例,推导出其占据屏幕坐标的比例,就得到了蝴蝶飞行目标的坐标
            float tmp_rgbaMat_height = (float)tmp_rgbaMat.height();
            float tmp_rgbaMat_width = (float)tmp_rgbaMat.width();
            float x = (float)array_pt[0].x;
            float y = (float)array_pt[0].y;
            //print("tmp_rgbaMat_width:" + tmp_rgbaMat_width + ";tmp_rgbaMat_height:" + tmp_rgbaMat_height + ";array_pt[0].x:"+ x+ ";array_pt[0].y:" +y);
            //计算目标点占比Mat比例
            float x_scale = (float)x / (float)tmp_rgbaMat_width;
            float y_scale = (float)y / (float)tmp_rgbaMat_height;
            //print("目标点占比Mat横方向比例:" + x_scale + ";目标点占比Mat纵方向比例:" + y_scale);            

            Vector3 vec3_tmp = new Vector3(x_scale* tmp_rgbaMat_width,(1 - y_scale) * tmp_rgbaMat_height, 100);
            obj_butterflyTarget.transform.position=Camera.main.ScreenToWorldPoint(vec3_tmp);
            
            print("obj_butterflyTarget.transform.position:"+ obj_butterflyTarget.transform.position);     
            
            Utils.matToTexture2D(tmp_rgbaMat, texture);
        }        

        /// <summary>
        /// Raises the destroy event.
        /// </summary>
        void OnDestroy ()
        {
            webCamTextureToMatHelper.Dispose ();

            if (detector != null)
                detector.Dispose ();
        }

        /// <summary>
        /// Raises the back button click event.
        /// </summary>
        public void OnBackButtonClick ()
        {
            SceneManager.LoadScene ("OpenCVForUnityExample");
        }

        /// <summary>
        /// Raises the play button click event.
        /// </summary>
        public void OnPlayButtonClick ()
        {
            webCamTextureToMatHelper.Play ();
        }

        /// <summary>
        /// Raises the pause button click event.
        /// </summary>
        public void OnPauseButtonClick ()
        {
            webCamTextureToMatHelper.Pause ();
        }

        /// <summary>
        /// Raises the stop button click event.
        /// </summary>
        public void OnStopButtonClick ()
        {
            webCamTextureToMatHelper.Stop ();
        }

        /// <summary>
        /// Raises the change camera button click event.
        /// </summary>
        public void OnChangeCameraButtonClick ()
        {
            webCamTextureToMatHelper.requestedIsFrontFacing = !webCamTextureToMatHelper.IsFrontFacing ();
        }
    }
}

1、My_test10_WebCamTextureToMatHelper

①主要是复制一下WebCamTextureToMatHelperExample代码,改一下内部名字为My_test10_WebCamTextureToMatHelper就可以了,其他没有动,目的为了只修改My_test10_WebCamTextureToMatHelper代码不动它原本代码

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
using OpenCVForUnity.CoreModule;
using OpenCVForUnity.UnityUtils;

namespace OpenCVForUnity.UnityUtils.Helper
{
    /// <summary>
    /// WebcamTexture to mat helper.
    /// v 1.1.0
    /// </summary>
    public class My_test10_WebCamTextureToMatHelper : MonoBehaviour
    {
        /// <summary>
        /// Set the name of the camera device to use. (or device index number)
        /// </summary>
        [SerializeField, FormerlySerializedAs ("requestedDeviceName"), TooltipAttribute ("Set the name of the device to use. (or device index number)")]
        protected string _requestedDeviceName = null;

        public virtual string requestedDeviceName {
            get { return _requestedDeviceName; }
            set {
                _requestedDeviceName = value;
                if (hasInitDone) {
                    Initialize ();
                }
            }
        }

        /// <summary>
        /// Set the width of camera.
        /// </summary>
        [SerializeField, FormerlySerializedAs ("requestedWidth"), TooltipAttribute ("Set the width of camera.")]
        protected int _requestedWidth = 640;

        public virtual int requestedWidth {
            get { return _requestedWidth; }
            set {
                _requestedWidth = (int)Mathf.Clamp (value, 0f, float.MaxValue);
                if (hasInitDone) {
                    Initialize ();
                }
            }
        }

        /// <summary>
        /// Set the height of camera.
        /// </summary>
        [SerializeField, FormerlySerializedAs ("requestedHeight"), TooltipAttribute ("Set the height of camera.")]
        protected int _requestedHeight = 480;

        public virtual int requestedHeight {
            get { return _requestedHeight; }
            set {
                _requestedHeight = (int)Mathf.Clamp (value, 0f, float.MaxValue);
                if (hasInitDone) {
                    Initialize ();
                }
            }
        }

        /// <summary>
        /// Set whether to use the front facing camera.
        /// </summary>
        [SerializeField, FormerlySerializedAs ("requestedIsFrontFacing"), TooltipAttribute ("Set whether to use the front facing camera.")]
        protected bool _requestedIsFrontFacing = false;

        public virtual bool requestedIsFrontFacing {
            get { return _requestedIsFrontFacing; }
            set {
                _requestedIsFrontFacing = value;
                if (hasInitDone) {
                    Initialize (_requestedIsFrontFacing, requestedFPS, rotate90Degree);
                }
            }
        }

        /// <summary>
        /// Set the frame rate of camera.
        /// </summary>
        [SerializeField, FormerlySerializedAs ("requestedFPS"), TooltipAttribute ("Set the frame rate of camera.")]
        protected float _requestedFPS = 30f;

        public virtual float requestedFPS {
            get { return _requestedFPS; }
            set {
                _requestedFPS = Mathf.Clamp (value, -1f, float.MaxValue);
                if (hasInitDone) {
                    bool isPlaying = IsPlaying ();
                    Stop ();
                    webCamTexture.requestedFPS = _requestedFPS;
                    if (isPlaying)
                        Play ();
                }
            }
        }

        /// <summary>
        /// Sets whether to rotate camera frame 90 degrees. (clockwise)
        /// </summary>
        [SerializeField, FormerlySerializedAs ("rotate90Degree"), TooltipAttribute ("Sets whether to rotate camera frame 90 degrees. (clockwise)")]
        protected bool _rotate90Degree = false;

        public virtual bool rotate90Degree {
            get { return _rotate90Degree; }
            set {
                _rotate90Degree = value;
                if (hasInitDone) {
                    Initialize ();
                }
            }
        }

        /// <summary>
        /// Determines if flips vertically.
        /// </summary>
        [SerializeField, FormerlySerializedAs ("flipVertical"), TooltipAttribute ("Determines if flips vertically.")]
        protected bool _flipVertical = false;

        public virtual bool flipVertical {
            get { return _flipVertical; }
            set { _flipVertical = value; }
        }

        /// <summary>
        /// Determines if flips horizontal.
        /// </summary>
        [SerializeField, FormerlySerializedAs ("flipHorizontal"), TooltipAttribute ("Determines if flips horizontal.")]
        protected bool _flipHorizontal = false;

        public virtual bool flipHorizontal {
            get { return _flipHorizontal; }
            set { _flipHorizontal = value; }
        }

        /// <summary>
        /// The number of frames before the initialization process times out.
        /// </summary>
        [SerializeField, FormerlySerializedAs ("timeoutFrameCount"), TooltipAttribute ("The number of frames before the initialization process times out.")]
        protected int _timeoutFrameCount = 300;

        public virtual int timeoutFrameCount {
            get { return _timeoutFrameCount; }
            set { _timeoutFrameCount = (int)Mathf.Clamp (value, 0f, float.MaxValue); }
        }

        /// <summary>
        /// UnityEvent that is triggered when this instance is initialized.
        /// </summary>
        public UnityEvent onInitialized;

        /// <summary>
        /// UnityEvent that is triggered when this instance is disposed.
        /// </summary>
        public UnityEvent onDisposed;

        /// <summary>
        /// UnityEvent that is triggered when this instance is error Occurred.
        /// </summary>
        public ErrorUnityEvent onErrorOccurred;

        /// <summary>
        /// The active WebcamTexture.
        /// </summary>
        protected WebCamTexture webCamTexture;

        /// <summary>
        /// The active WebcamDevice.
        /// </summary>
        protected WebCamDevice webCamDevice;

        /// <summary>
        /// The frame mat.
        /// </summary>
        protected Mat frameMat;

        /// <summary>
        /// The rotated frame mat
        /// </summary>
        protected Mat rotatedFrameMat;

        /// <summary>
        /// The buffer colors.
        /// </summary>
        protected Color32[] colors;

        /// <summary>
        /// Indicates whether this instance is waiting for initialization to complete.
        /// </summary>
        protected bool isInitWaiting = false;

        /// <summary>
        /// Indicates whether this instance has been initialized.
        /// </summary>
        protected bool hasInitDone = false;

        /// <summary>
        /// The initialization coroutine.
        /// </summary>
        protected IEnumerator initCoroutine;

        /// <summary>
        /// The orientation of the screen.
        /// </summary>
        protected ScreenOrientation screenOrientation;

        /// <summary>
        /// The width of the screen.
        /// </summary>
        protected int screenWidth;

        /// <summary>
        /// The height of the screen.
        /// </summary>
        protected int screenHeight;

        /// <summary>
        /// Indicates whether this instance avoids the front camera low light issue that occurs in only some Android devices (e.g. Google Pixel, Pixel2).
        /// Sets compulsorily the requestedFPS parameter to 15 (only when using the front camera), to avoid the problem of the WebCamTexture image becoming low light.
        /// https://forum.unity.com/threads/android-webcamtexture-in-low-light-only-some-models.520656/
        /// https://forum.unity.com/threads/released-opencv-for-unity.277080/page-33#post-3445178
        /// </summary>
        public bool avoidAndroidFrontCameraLowLightIssue = false;

        [System.Serializable]
        public enum ErrorCode : int
        {
            UNKNOWN = 0,
            CAMERA_DEVICE_NOT_EXIST = 1,
            TIMEOUT = 2,
        }

        [System.Serializable]
        public class ErrorUnityEvent : UnityEngine.Events.UnityEvent<ErrorCode>
        {

        }

        protected virtual void OnValidate ()
        {
            _requestedWidth = (int)Mathf.Clamp (_requestedWidth, 0f, float.MaxValue);
            _requestedHeight = (int)Mathf.Clamp (_requestedHeight, 0f, float.MaxValue);
            _requestedFPS = Mathf.Clamp (_requestedFPS, -1f, float.MaxValue);
            _timeoutFrameCount = (int)Mathf.Clamp (_timeoutFrameCount, 0f, float.MaxValue);
        }

        // Update is called once per frame
        protected virtual void Update ()
        {
            if (hasInitDone) {
                // Catch the orientation change of the screen and correct the mat image to the correct direction.
                if (screenOrientation != Screen.orientation && (screenWidth != Screen.width || screenHeight != Screen.height)) {

                    if (onDisposed != null)
                        onDisposed.Invoke ();

                    if (frameMat != null) {
                        frameMat.Dispose ();
                        frameMat = null;
                    }
                    if (rotatedFrameMat != null) {
                        rotatedFrameMat.Dispose ();
                        rotatedFrameMat = null;
                    }

                    frameMat = new Mat (webCamTexture.height, webCamTexture.width, CvType.CV_8UC4, new Scalar (0, 0, 0, 255));
                    screenOrientation = Screen.orientation;
                    screenWidth = Screen.width;
                    screenHeight = Screen.height;

                    bool isRotatedFrame = false;
                    #if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
                    if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown)
                    {
                        if (!rotate90Degree)
                            isRotatedFrame = true;
                    }
                    else if (rotate90Degree)
                    {
                        isRotatedFrame = true;
                    }
                    #else
                    if (rotate90Degree)
                        isRotatedFrame = true;
                    #endif
                    if (isRotatedFrame)
                        rotatedFrameMat = new Mat (webCamTexture.width, webCamTexture.height, CvType.CV_8UC4, new Scalar (0, 0, 0, 255));

                    if (onInitialized != null)
                        onInitialized.Invoke ();
                } else {
                    screenWidth = Screen.width;
                    screenHeight = Screen.height;
                }
            }
        }

        /// <summary>
        /// Raises the destroy event.
        /// </summary>
        protected virtual void OnDestroy ()
        {
            Dispose ();
        }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        public virtual void Initialize ()
        {
            if (isInitWaiting) {
                CancelInitCoroutine ();
                ReleaseResources ();
            }

            if (onInitialized == null)
                onInitialized = new UnityEvent ();
            if (onDisposed == null)
                onDisposed = new UnityEvent ();
            if (onErrorOccurred == null)
                onErrorOccurred = new ErrorUnityEvent ();

            initCoroutine = _Initialize ();
            StartCoroutine (initCoroutine);
        }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        /// <param name="requestedWidth">Requested width.</param>
        /// <param name="requestedHeight">Requested height.</param>
        public virtual void Initialize (int requestedWidth, int requestedHeight)
        {
            if (isInitWaiting) {
                CancelInitCoroutine ();
                ReleaseResources ();
            }

            this._requestedWidth = requestedWidth;
            this._requestedHeight = requestedHeight;
            if (onInitialized == null)
                onInitialized = new UnityEvent ();
            if (onDisposed == null)
                onDisposed = new UnityEvent ();
            if (onErrorOccurred == null)
                onErrorOccurred = new ErrorUnityEvent ();

            initCoroutine = _Initialize ();
            StartCoroutine (initCoroutine);
        }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        /// <param name="requestedIsFrontFacing">If set to <c>true</c> requested to using the front camera.</param>
        /// <param name="requestedFPS">Requested FPS.</param>
        /// <param name="rotate90Degree">If set to <c>true</c> requested to rotate camera frame 90 degrees. (clockwise)</param>
        public virtual void Initialize (bool requestedIsFrontFacing, float requestedFPS = 30f, bool rotate90Degree = false)
        {
            if (isInitWaiting) {
                CancelInitCoroutine ();
                ReleaseResources ();
            }

            _requestedDeviceName = null;
            this._requestedIsFrontFacing = requestedIsFrontFacing;
            this._requestedFPS = requestedFPS;
            this._rotate90Degree = rotate90Degree;
            if (onInitialized == null)
                onInitialized = new UnityEvent ();
            if (onDisposed == null)
                onDisposed = new UnityEvent ();
            if (onErrorOccurred == null)
                onErrorOccurred = new ErrorUnityEvent ();

            initCoroutine = _Initialize ();
            StartCoroutine (initCoroutine);
        }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        /// <param name="deviceName">Device name.</param>
        /// <param name="requestedWidth">Requested width.</param>
        /// <param name="requestedHeight">Requested height.</param>
        /// <param name="requestedIsFrontFacing">If set to <c>true</c> requested to using the front camera.</param>
        /// <param name="requestedFPS">Requested FPS.</param>
        /// <param name="rotate90Degree">If set to <c>true</c> requested to rotate camera frame 90 degrees. (clockwise)</param>
        public virtual void Initialize (string deviceName, int requestedWidth, int requestedHeight, bool requestedIsFrontFacing = false, float requestedFPS = 30f, bool rotate90Degree = false)
        {
            if (isInitWaiting) {
                CancelInitCoroutine ();
                ReleaseResources ();
            }

            this._requestedDeviceName = deviceName;
            this._requestedWidth = requestedWidth;
            this._requestedHeight = requestedHeight;
            this._requestedIsFrontFacing = requestedIsFrontFacing;
            this._requestedFPS = requestedFPS;
            this._rotate90Degree = rotate90Degree;
            if (onInitialized == null)
                onInitialized = new UnityEvent ();
            if (onDisposed == null)
                onDisposed = new UnityEvent ();
            if (onErrorOccurred == null)
                onErrorOccurred = new ErrorUnityEvent ();

            initCoroutine = _Initialize ();
            StartCoroutine (initCoroutine);
        }

        /// <summary>
        /// Initializes this instance by coroutine.
        /// </summary>
        protected virtual IEnumerator _Initialize ()
        {
            if (hasInitDone) {
                ReleaseResources ();

                if (onDisposed != null)
                    onDisposed.Invoke ();
            }

            isInitWaiting = true;

            float requestedFPS = this.requestedFPS;

            // Creates the camera
            if (!String.IsNullOrEmpty (requestedDeviceName)) {
                int requestedDeviceIndex = -1;
                if (Int32.TryParse (requestedDeviceName, out requestedDeviceIndex)) {
                    if (requestedDeviceIndex >= 0 && requestedDeviceIndex < WebCamTexture.devices.Length) {
                        webCamDevice = WebCamTexture.devices [requestedDeviceIndex];

                        if (avoidAndroidFrontCameraLowLightIssue && webCamDevice.isFrontFacing == true)
                            requestedFPS = 15f;

                        if (requestedFPS < 0) {
                            webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight);
                        } else {
                            webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, (int)requestedFPS);
                        }
                    }
                } else {
                    for (int cameraIndex = 0; cameraIndex < WebCamTexture.devices.Length; cameraIndex++) {
                        if (WebCamTexture.devices [cameraIndex].name == requestedDeviceName) {
                            webCamDevice = WebCamTexture.devices [cameraIndex];

                            if (avoidAndroidFrontCameraLowLightIssue && webCamDevice.isFrontFacing == true)
                                requestedFPS = 15f;

                            if (requestedFPS < 0) {
                                webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight);
                            } else {
                                webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, (int)requestedFPS);
                            }
                            break;
                        }
                    }
                }
                if (webCamTexture == null)
                    Debug.Log ("Cannot find camera device " + requestedDeviceName + ".");
            }

            if (webCamTexture == null) {
                // Checks how many and which cameras are available on the device
                for (int cameraIndex = 0; cameraIndex < WebCamTexture.devices.Length; cameraIndex++) {
                    if (WebCamTexture.devices [cameraIndex].isFrontFacing == requestedIsFrontFacing) {
                        webCamDevice = WebCamTexture.devices [cameraIndex];

                        if (avoidAndroidFrontCameraLowLightIssue && webCamDevice.isFrontFacing == true)
                            requestedFPS = 15f;

                        if (requestedFPS < 0) {
                            webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight);
                        } else {
                            webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, (int)requestedFPS);
                        }
                        break;
                    }
                }
            }

            if (webCamTexture == null) {
                if (WebCamTexture.devices.Length > 0) {
                    webCamDevice = WebCamTexture.devices [0];

                    if (avoidAndroidFrontCameraLowLightIssue && webCamDevice.isFrontFacing == true)
                        requestedFPS = 15f;

                    if (requestedFPS < 0) {
                        webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight);
                    } else {
                        webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, (int)requestedFPS);
                    }
                } else {
                    isInitWaiting = false;

                    if (onErrorOccurred != null)
                        onErrorOccurred.Invoke (ErrorCode.CAMERA_DEVICE_NOT_EXIST);

                    yield break;
                }
            }

            // Starts the camera
            webCamTexture.Play ();

            int initFrameCount = 0;
            bool isTimeout = false;

            while (true) {
                if (initFrameCount > timeoutFrameCount) {
                    isTimeout = true;
                    break;
                }
                // If you want to use webcamTexture.width and webcamTexture.height on iOS, you have to wait until webcamTexture.didUpdateThisFrame == 1, otherwise these two values will be equal to 16. (http://forum.unity3d.com/threads/webcamtexture-and-error-0x0502.123922/)
                #if UNITY_IOS && !UNITY_EDITOR && (UNITY_4_6_3 || UNITY_4_6_4 || UNITY_5_0_0 || UNITY_5_0_1)
                else if (webCamTexture.width > 16 && webCamTexture.height > 16) {
                #else
                else if (webCamTexture.didUpdateThisFrame) {
                    #if UNITY_IOS && !UNITY_EDITOR && UNITY_5_2
                    while (webCamTexture.width <= 16) {
                        if (initFrameCount > timeoutFrameCount) {
                            isTimeout = true;
                            break;
                        }else {
                            initFrameCount++;
                        }
                        webCamTexture.GetPixels32 ();
                        yield return new WaitForEndOfFrame ();
                    }
                    if (isTimeout) break;
                    #endif
                    #endif

                    Debug.Log ("WebCamTextureToMatHelper:: " + "devicename:" + webCamTexture.deviceName + " name:" + webCamTexture.name + " width:" + webCamTexture.width + " height:" + webCamTexture.height + " fps:" + webCamTexture.requestedFPS
                    + " videoRotationAngle:" + webCamTexture.videoRotationAngle + " videoVerticallyMirrored:" + webCamTexture.videoVerticallyMirrored + " isFrongFacing:" + webCamDevice.isFrontFacing);

                    if (colors == null || colors.Length != webCamTexture.width * webCamTexture.height)
                        colors = new Color32[webCamTexture.width * webCamTexture.height];

                    frameMat = new Mat (webCamTexture.height, webCamTexture.width, CvType.CV_8UC4);
                    screenOrientation = Screen.orientation;
                    screenWidth = Screen.width;
                    screenHeight = Screen.height;

                    bool isRotatedFrame = false;
                    #if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
                    if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown)
                    {
                        if (!rotate90Degree)
                            isRotatedFrame = true;
                    }
                    else if (rotate90Degree)
                    {
                        isRotatedFrame = true;
                    }
                    #else
                    if (rotate90Degree)
                        isRotatedFrame = true;
                    #endif
                    if (isRotatedFrame)
                        rotatedFrameMat = new Mat (webCamTexture.width, webCamTexture.height, CvType.CV_8UC4);

                    isInitWaiting = false;
                    hasInitDone = true;
                    initCoroutine = null;

                    if (onInitialized != null)
                        onInitialized.Invoke ();

                    break;
                } else {
                    initFrameCount++;
                    yield return null;
                }
            }

            if (isTimeout) {
                webCamTexture.Stop ();
                webCamTexture = null;
                isInitWaiting = false;
                initCoroutine = null;

                if (onErrorOccurred != null)
                    onErrorOccurred.Invoke (ErrorCode.TIMEOUT);
            }
        }

        /// <summary>
        /// Indicates whether this instance has been initialized.
        /// </summary>
        /// <returns><c>true</c>, if this instance has been initialized, <c>false</c> otherwise.</returns>
        public virtual bool IsInitialized ()
        {
            return hasInitDone;
        }

        /// <summary>
        /// Starts the camera.
        /// </summary>
        public virtual void Play ()
        {
            if (hasInitDone)
                webCamTexture.Play ();
        }

        /// <summary>
        /// Pauses the active camera.
        /// </summary>
        public virtual void Pause ()
        {
            if (hasInitDone)
                webCamTexture.Pause ();
        }

        /// <summary>
        /// Stops the active camera.
        /// </summary>
        public virtual void Stop ()
        {
            if (hasInitDone)
                webCamTexture.Stop ();
        }

        /// <summary>
        /// Indicates whether the active camera is currently playing.
        /// </summary>
        /// <returns><c>true</c>, if the active camera is playing, <c>false</c> otherwise.</returns>
        public virtual bool IsPlaying ()
        {
            return hasInitDone ? webCamTexture.isPlaying : false;
        }

        /// <summary>
        /// Indicates whether the active camera device is currently front facng.
        /// </summary>
        /// <returns><c>true</c>, if the active camera device is front facng, <c>false</c> otherwise.</returns>
        public virtual bool IsFrontFacing ()
        {
            return hasInitDone ? webCamDevice.isFrontFacing : false;
        }

        /// <summary>
        /// Returns the active camera device name.
        /// </summary>
        /// <returns>The active camera device name.</returns>
        public virtual string GetDeviceName ()
        {
            return hasInitDone ? webCamTexture.deviceName : "";
        }

        /// <summary>
        /// Returns the active camera width.
        /// </summary>
        /// <returns>The active camera width.</returns>
        public virtual int GetWidth ()
        {
            if (!hasInitDone)
                return -1;
            return (rotatedFrameMat != null) ? frameMat.height () : frameMat.width ();
        }

        /// <summary>
        /// Returns the active camera height.
        /// </summary>
        /// <returns>The active camera height.</returns>
        public virtual int GetHeight ()
        {
            if (!hasInitDone)
                return -1;
            return (rotatedFrameMat != null) ? frameMat.width () : frameMat.height ();
        }

        /// <summary>
        /// Returns the active camera framerate.
        /// </summary>
        /// <returns>The active camera framerate.</returns>
        public virtual float GetFPS ()
        {
            return hasInitDone ? webCamTexture.requestedFPS : -1f;
        }

        /// <summary>
        /// Returns the active WebcamTexture.
        /// </summary>
        /// <returns>The active WebcamTexture.</returns>
        public virtual WebCamTexture GetWebCamTexture ()
        {
            return hasInitDone ? webCamTexture : null;
        }

        /// <summary>
        /// Returns the active WebcamDevice.
        /// </summary>
        /// <returns>The active WebcamDevice.</returns>
        public virtual WebCamDevice GetWebCamDevice ()
        {
            return webCamDevice;
        }

        /// <summary>
        /// Returns the camera to world matrix.
        /// </summary>
        /// <returns>The camera to world matrix.</returns>
        public virtual Matrix4x4 GetCameraToWorldMatrix ()
        {
            return Camera.main.cameraToWorldMatrix;
        }

        /// <summary>
        /// Returns the projection matrix matrix.
        /// </summary>
        /// <returns>The projection matrix.</returns>
        public virtual Matrix4x4 GetProjectionMatrix ()
        {
            return Camera.main.projectionMatrix;
        }

        /// <summary>
        /// Indicates whether the video buffer of the frame has been updated.
        /// </summary>
        /// <returns><c>true</c>, if the video buffer has been updated <c>false</c> otherwise.</returns>
        public virtual bool DidUpdateThisFrame ()
        {
            if (!hasInitDone)
                return false;

            #if UNITY_IOS && !UNITY_EDITOR && (UNITY_4_6_3 || UNITY_4_6_4 || UNITY_5_0_0 || UNITY_5_0_1)
            if (webCamTexture.width > 16 && webCamTexture.height > 16) {
                return true;
            } else {
                return false;
            }
            #else
            return webCamTexture.didUpdateThisFrame;
            #endif
        }

        /// <summary>
        /// Gets the mat of the current frame.
        /// The Mat object's type is 'CV_8UC4' (RGBA).
        /// </summary>
        /// <returns>The mat of the current frame.</returns>
        public virtual Mat GetMat ()
        {
            if (!hasInitDone || !webCamTexture.isPlaying) {
                return (rotatedFrameMat != null) ? rotatedFrameMat : frameMat;
            }

            Utils.webCamTextureToMat (webCamTexture, frameMat, colors, false);

            #if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
            if (rotatedFrameMat != null)
            {
                if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown)
                {
                    // (Orientation is Portrait, rotate90Degree is false)
                    if (webCamDevice.isFrontFacing)
                    {
                        FlipMat (frameMat, !flipHorizontal, !flipVertical);
                    }
                    else
                    {
                        FlipMat (frameMat, flipHorizontal, flipVertical);
                    }
                }
                else
                {
                    // (Orientation is Landscape, rotate90Degrees=true)
                    FlipMat (frameMat, flipVertical, flipHorizontal);
                }
                Core.rotate (frameMat, rotatedFrameMat, Core.ROTATE_90_CLOCKWISE);
                return rotatedFrameMat;
            }
            else
            {
                if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown)
                {
                    // (Orientation is Portrait, rotate90Degree is ture)
                    if (webCamDevice.isFrontFacing)
                    {
                        FlipMat (frameMat, flipHorizontal, flipVertical);
                    }
                    else
                    {
                        FlipMat (frameMat, !flipHorizontal, !flipVertical);
                    }
                }
                else
                {
                    // (Orientation is Landscape, rotate90Degree is false)
                    FlipMat (frameMat, flipVertical, flipHorizontal);
                }
                return frameMat;
            }
            #else
            FlipMat (frameMat, flipVertical, flipHorizontal);
            if (rotatedFrameMat != null) {                
                Core.rotate (frameMat, rotatedFrameMat, Core.ROTATE_90_CLOCKWISE);
                return rotatedFrameMat;
            } else {
                return frameMat;
            }
            #endif
        }

        /// <summary>
        /// Flips the mat.
        /// </summary>
        /// <param name="mat">Mat.</param>
        protected virtual void FlipMat (Mat mat, bool flipVertical, bool flipHorizontal)
        {
            //Since the order of pixels of WebCamTexture and Mat is opposite, the initial value of flipCode is set to 0 (flipVertical).
            int flipCode = 0;

            if (webCamDevice.isFrontFacing) {
                if (webCamTexture.videoRotationAngle == 0) {
                    flipCode = -1;
                } else if (webCamTexture.videoRotationAngle == 90) {
                    flipCode = -1;
                }
                if (webCamTexture.videoRotationAngle == 180) {
                    flipCode = int.MinValue;
                } else if (webCamTexture.videoRotationAngle == 270) {
                    flipCode = int.MinValue;
                }
            } else {
                if (webCamTexture.videoRotationAngle == 180) {
                    flipCode = 1;
                } else if (webCamTexture.videoRotationAngle == 270) {
                    flipCode = 1;
                }
            }

            if (flipVertical) {
                if (flipCode == int.MinValue) {
                    flipCode = 0;
                } else if (flipCode == 0) {
                    flipCode = int.MinValue;
                } else if (flipCode == 1) {
                    flipCode = -1;
                } else if (flipCode == -1) {
                    flipCode = 1;
                }
            }

            if (flipHorizontal) {
                if (flipCode == int.MinValue) {
                    flipCode = 1;
                } else if (flipCode == 0) {
                    flipCode = -1;
                } else if (flipCode == 1) {
                    flipCode = int.MinValue;
                } else if (flipCode == -1) {
                    flipCode = 0;
                }
            }

            if (flipCode > int.MinValue) {
                Core.flip (mat, mat, flipCode);
            }
        }

        /// <summary>
        /// Gets the buffer colors.
        /// </summary>
        /// <returns>The buffer colors.</returns>
        public virtual Color32[] GetBufferColors ()
        {
            return colors;
        }

        /// <summary>
        /// Cancel Init Coroutine.
        /// </summary>
        protected virtual void CancelInitCoroutine ()
        {
            if (initCoroutine != null) {
                StopCoroutine (initCoroutine);
                ((IDisposable)initCoroutine).Dispose ();
                initCoroutine = null;
            }
        }

        /// <summary>
        /// To release the resources.
        /// </summary>
        protected virtual void ReleaseResources ()
        {
            isInitWaiting = false;
            hasInitDone = false;

            if (webCamTexture != null) {
                webCamTexture.Stop ();
                WebCamTexture.Destroy (webCamTexture);
                webCamTexture = null;
            }
            if (frameMat != null) {
                frameMat.Dispose ();
                frameMat = null;
            }
            if (rotatedFrameMat != null) {
                rotatedFrameMat.Dispose ();
                rotatedFrameMat = null;
            }
        }

        /// <summary>
        /// Releases all resource used by the <see cref="WebCamTextureToMatHelper"/> object.
        /// </summary>
        /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="WebCamTextureToMatHelper"/>. The
        /// <see cref="Dispose"/> method leaves the <see cref="WebCamTextureToMatHelper"/> in an unusable state. After
        /// calling <see cref="Dispose"/>, you must release all references to the <see cref="WebCamTextureToMatHelper"/> so
        /// the garbage collector can reclaim the memory that the <see cref="WebCamTextureToMatHelper"/> was occupying.</remarks>
        public virtual void Dispose ()
        {
            if (colors != null)
                colors = null;

            if (isInitWaiting) {
                CancelInitCoroutine ();
                ReleaseResources ();
            } else if (hasInitDone) {
                ReleaseResources ();

                if (onDisposed != null)
                    onDisposed.Invoke ();
            }
        }
    }
}

1、效果:Cube随着手指最高点移动

 

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值