目录
1、参考我之前写的OpenCVForUnity文章,一步步走来不容易,里面好多的函数名字和Opencv不一样,并且OpenCVForUnity文档都没有解释,只能自己瞎琢磨
1、复制OpenCVForUnity中HandPoseEstimationExample案例
1、My_test10_findHandHighestPoint
①将HandPoseEstimationExample代码里面的Update删除掉,一些没有用到的删除掉,然后写上自己的代码,主要是Test_hsv06函数
1、My_test10_WebCamTextureToMatHelper
一、目的:找到手指的最高点
一、参考:
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随着手指最高点移动