update 1.1.6
|
@ -0,0 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 064069bd9d3917b4898352dae28c624f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
|
@ -0,0 +1,29 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: eff_glitter_2
|
||||
m_Shader: {fileID: 10720, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
data:
|
||||
first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 2800000, guid: b0ffb540d124f4144ad76e36fe41b91d, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats: {}
|
||||
m_Colors:
|
||||
data:
|
||||
first:
|
||||
name: _Color
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
|
@ -0,0 +1,29 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: eff_par_1
|
||||
m_Shader: {fileID: 10720, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
data:
|
||||
first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 2800000, guid: f8b1a36af41214f079689857ae15f1ea, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats: {}
|
||||
m_Colors:
|
||||
data:
|
||||
first:
|
||||
name: _Color
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
|
@ -0,0 +1,37 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: eff_smoke_2
|
||||
m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
data:
|
||||
first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 2800000, guid: 3c006f387d1b24898aa7ed5056023bb3, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
data:
|
||||
first:
|
||||
name: _InvFade
|
||||
second: 1
|
||||
m_Colors:
|
||||
data:
|
||||
first:
|
||||
name: _Color
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
||||
data:
|
||||
first:
|
||||
name: _TintColor
|
||||
second: {r: .5, g: .5, b: .5, a: .5}
|
До Ширина: | Высота: | Размер: 22 KiB После Ширина: | Высота: | Размер: 22 KiB |
До Ширина: | Высота: | Размер: 34 KiB После Ширина: | Высота: | Размер: 34 KiB |
До Ширина: | Высота: | Размер: 192 KiB После Ширина: | Высота: | Размер: 192 KiB |
|
@ -0,0 +1,123 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using OpenCVForUnity;
|
||||
|
||||
namespace OpenCVFaceTracker
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Face detector.
|
||||
/// Code is the rewrite of https://github.com/MasteringOpenCV/code/tree/master/Chapter6_NonRigidFaceTracking using the “OpenCV for Unity”.
|
||||
/// </summary>
|
||||
public class FaceDetector
|
||||
{
|
||||
|
||||
|
||||
string detector_fname; //file containing cascade classifier
|
||||
Vector3 detector_offset; //offset from center of detection
|
||||
Mat reference; //reference shape
|
||||
CascadeClassifier detector;
|
||||
|
||||
public FaceDetector()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public List<Point[]> detect(Mat im, float scaleFactor, int minNeighbours, OpenCVForUnity.Size minSize)
|
||||
{
|
||||
//convert image to greyscale
|
||||
Mat gray = null;
|
||||
if (im.channels() == 1)
|
||||
{
|
||||
gray = im;
|
||||
} else
|
||||
{
|
||||
gray = new Mat();
|
||||
Imgproc.cvtColor(im, gray, Imgproc.COLOR_RGBA2GRAY);
|
||||
}
|
||||
|
||||
|
||||
using (Mat equalizeHistMat = new Mat ())
|
||||
using (MatOfRect faces = new MatOfRect ())
|
||||
{
|
||||
|
||||
Imgproc.equalizeHist(gray, equalizeHistMat);
|
||||
|
||||
detector.detectMultiScale(equalizeHistMat, faces, scaleFactor, minNeighbours, 0
|
||||
| Objdetect.CASCADE_FIND_BIGGEST_OBJECT
|
||||
| Objdetect.CASCADE_SCALE_IMAGE, minSize, new Size());
|
||||
|
||||
|
||||
if (faces.rows() < 1)
|
||||
{
|
||||
return new List<Point[]>();
|
||||
}
|
||||
return convertMatOfRectToPoints(faces);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<Point[]> convertMatOfRectToPoints(MatOfRect rects)
|
||||
{
|
||||
List<OpenCVForUnity.Rect> R = rects.toList();
|
||||
|
||||
List<Point[]> points = new List<Point[]>(R.Count);
|
||||
|
||||
int n = reference.rows() / 2;
|
||||
float[] reference_float = new float[reference.total()];
|
||||
Utils.copyFromMat<float>(reference, reference_float);
|
||||
|
||||
foreach (var r in R)
|
||||
{
|
||||
|
||||
Vector3 scale = detector_offset * r.width;
|
||||
Point[] p = new Point[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
p [i] = new Point();
|
||||
p [i].x = scale.z * reference_float [2 * i] + r.x + 0.5 * r.width + scale.x;
|
||||
p [i].y = scale.z * reference_float [(2 * i) + 1] + r.y + 0.5 * r.height + scale.y;
|
||||
}
|
||||
|
||||
points.Add(p);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
public void read(object root_json)
|
||||
{
|
||||
IDictionary detector_json = (IDictionary)root_json;
|
||||
|
||||
detector_fname = (string)detector_json ["fname"];
|
||||
// Debug.Log ("detector_fname " + detector_fname);
|
||||
|
||||
|
||||
detector_offset = new Vector3((float)(double)detector_json ["x offset"], (float)(double)detector_json ["y offset"], (float)(double)detector_json ["z offset"]);
|
||||
// Debug.Log ("detector_offset " + detector_offset.ToString ());
|
||||
|
||||
|
||||
IDictionary reference_json = (IDictionary)detector_json ["reference"];
|
||||
|
||||
|
||||
reference = new Mat((int)(long)reference_json ["rows"], (int)(long)reference_json ["cols"], CvType.CV_32F);
|
||||
// Debug.Log ("reference " + reference.ToString ());
|
||||
|
||||
IList data_json = (IList)reference_json ["data"];
|
||||
float[] data = new float[reference.rows() * reference.cols()];
|
||||
for (int i = 0; i < data_json.Count; i++)
|
||||
{
|
||||
data [i] = (float)(double)data_json [i];
|
||||
}
|
||||
Utils.copyToMat(data, reference);
|
||||
// Debug.Log ("reference dump " + reference.dump ());
|
||||
|
||||
detector = new CascadeClassifier(Utils.getFilePath(detector_fname));
|
||||
// detector = new CascadeClassifier (System.IO.Path.Combine (Application.streamingAssetsPath, detector_fname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using OpenCVForUnity;
|
||||
using System.Collections.Generic;
|
||||
using MiniJSON;
|
||||
|
||||
#if UNITY_WSA
|
||||
using UnityEngine.Windows;
|
||||
using System.Text;
|
||||
#else
|
||||
using System.IO;
|
||||
#endif
|
||||
|
||||
namespace OpenCVFaceTracker
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Face tracker.
|
||||
/// Code is the rewrite of https://github.com/MasteringOpenCV/code/tree/master/Chapter6_NonRigidFaceTracking using the “OpenCV for Unity”.
|
||||
/// </summary>
|
||||
public class FaceTracker
|
||||
{
|
||||
|
||||
List<Point[]> points; //current tracked points
|
||||
FaceDetector detector; //detector for initialisation
|
||||
ShapeModel smodel; //shape model
|
||||
PatchModels pmodel; //feature detectors
|
||||
|
||||
public FaceTracker(string filepath)
|
||||
{
|
||||
if (filepath == null)
|
||||
{
|
||||
Debug.LogError("tracker_model file is not loaded.Please copy from “FaceTrackerSample/StreamingAssets/” to “Assets/StreamingAssets/” folder. ");
|
||||
}
|
||||
|
||||
points = new List<Point[]>();
|
||||
|
||||
string jsonText = null;
|
||||
|
||||
|
||||
#if UNITY_WSA
|
||||
var data = File.ReadAllBytes(filepath);
|
||||
jsonText = Encoding.UTF8.GetString(data, 0, data.Length);
|
||||
#else
|
||||
jsonText = File.ReadAllText(filepath);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// TextAsset textAsset = Resources.Load (filename) as TextAsset;
|
||||
// string jsonText = textAsset.text;
|
||||
|
||||
IDictionary json = (IDictionary)Json.Deserialize(jsonText);
|
||||
|
||||
IDictionary ft = (IDictionary)json ["ft object"];
|
||||
|
||||
detector = new FaceDetector();
|
||||
detector.read(ft ["detector"]);
|
||||
|
||||
smodel = new ShapeModel();
|
||||
smodel.read(ft ["smodel"]);
|
||||
|
||||
pmodel = new PatchModels();
|
||||
pmodel.read(ft ["pmodel"]);
|
||||
}
|
||||
|
||||
public List<Point[]> getPoints()
|
||||
{
|
||||
return points;
|
||||
}
|
||||
|
||||
public void addPoints(List<Point[]> points)
|
||||
{
|
||||
points.AddRange(points);
|
||||
}
|
||||
|
||||
public void addPoints(MatOfRect rects)
|
||||
{
|
||||
points.AddRange(detector.convertMatOfRectToPoints(rects));
|
||||
|
||||
}
|
||||
|
||||
public Point[] getConnections()
|
||||
{
|
||||
|
||||
Point[] c = new Point[smodel.C.rows()];
|
||||
int[] data = new int[c.Length * 2];
|
||||
Utils.copyFromMat<int>(smodel.C, data);
|
||||
|
||||
int len = c.Length;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
c [i] = new Point(data [i * 2], data [(i * 2) + 1]);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
//reset tracker
|
||||
points.Clear();
|
||||
}
|
||||
|
||||
public bool track(Mat im, FaceTrackerParams p)
|
||||
{
|
||||
if (points.Count <= 0)
|
||||
return false;
|
||||
|
||||
|
||||
//convert image to greyscale
|
||||
Mat gray = null;
|
||||
if (im.channels() == 1)
|
||||
{
|
||||
gray = im;
|
||||
} else
|
||||
{
|
||||
gray = new Mat();
|
||||
Imgproc.cvtColor(im, gray, Imgproc.COLOR_RGBA2GRAY);
|
||||
}
|
||||
|
||||
//initialise
|
||||
// if (!tracking)
|
||||
// points = detector.detect (gray, p.scaleFactor, p.minNeighbours, p.minSize);
|
||||
int count = points.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (points [i].Length != smodel.npts())
|
||||
return false;
|
||||
|
||||
//fit
|
||||
int size_count = p.ssize.Count;
|
||||
for (int level = 0; level < size_count; level++)
|
||||
{
|
||||
points [i] = fit(gray, points [i], p.ssize [level], p.robust, p.itol, p.ftol);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void draw(Mat im, Scalar pts_color, Scalar con_color)
|
||||
{
|
||||
|
||||
int[] smodel_C_int = new int[smodel.C.total()];
|
||||
Utils.copyFromMat<int>(smodel.C, smodel_C_int);
|
||||
|
||||
foreach (var point in points)
|
||||
{
|
||||
int n = point.Length;
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
int rows = smodel.C.rows();
|
||||
int cols = smodel.C.cols();
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
int j = smodel_C_int [i * cols], k = smodel_C_int [(i * cols) + 1];
|
||||
#if OPENCV_2
|
||||
Core.line(im, point[j], point[k], con_color, 1);
|
||||
#else
|
||||
Imgproc.line(im, point [j], point [k], con_color, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
#if OPENCV_2
|
||||
Core.circle (im, point [i], 1, pts_color, 2, Core.LINE_AA, 0);
|
||||
#else
|
||||
Imgproc.circle(im, point [i], 1, pts_color, 2, Core.LINE_AA, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Point[] fit(Mat image,
|
||||
Point[] init,
|
||||
OpenCVForUnity.Size ssize,
|
||||
bool robust,
|
||||
int itol,
|
||||
double ftol)
|
||||
{
|
||||
int n = smodel.npts();
|
||||
// assert((int(init.size())==n) && (pmodel.n_patches()==n));
|
||||
// Debug.Log ("init.size())==n " + init.Length + " " + n);
|
||||
// Debug.Log ("pmodel.n_patches()==n " + pmodel.n_patches () + " " + n);
|
||||
smodel.calc_params(init, new Mat(), 3.0f);
|
||||
Point[] pts = smodel.calc_shape();
|
||||
|
||||
//find facial features in image around current estimates
|
||||
Point[] peaks = pmodel.calc_peaks(image, pts, ssize);
|
||||
|
||||
//optimise
|
||||
if (!robust)
|
||||
{
|
||||
smodel.calc_params(peaks, new Mat(), 3.0f); //compute shape model parameters
|
||||
pts = smodel.calc_shape(); //update shape
|
||||
} else
|
||||
{
|
||||
using (Mat weight = new Mat (n, 1, CvType.CV_32F))
|
||||
using (Mat weight_sort = new Mat (n, 1, CvType.CV_32F))
|
||||
{
|
||||
|
||||
float[] weight_float = new float[weight.total()];
|
||||
Utils.copyFromMat<float>(weight, weight_float);
|
||||
float[] weight_sort_float = new float[weight_sort.total()];
|
||||
|
||||
Point[] pts_old = pts;
|
||||
for (int iter = 0; iter < itol; iter++)
|
||||
{
|
||||
//compute robust weight
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
using (MatOfPoint tmpMat = new MatOfPoint (new Point (pts [i].x - peaks [i].x, pts [i].y - peaks [i].y)))
|
||||
{
|
||||
weight_float [i] = (float)Core.norm(tmpMat);
|
||||
}
|
||||
}
|
||||
Utils.copyToMat(weight_float, weight);
|
||||
|
||||
Core.sort(weight, weight_sort, Core.SORT_EVERY_COLUMN | Core.SORT_ASCENDING);
|
||||
|
||||
|
||||
Utils.copyFromMat<float>(weight_sort, weight_sort_float);
|
||||
double var = 1.4826 * weight_sort_float [n / 2];
|
||||
|
||||
|
||||
if (var < 0.1)
|
||||
var = 0.1;
|
||||
|
||||
Core.pow(weight, 2, weight);
|
||||
|
||||
|
||||
Core.multiply(weight, new Scalar(-0.5 / (var * var)), weight);
|
||||
|
||||
Core.exp(weight, weight);
|
||||
|
||||
//compute shape model parameters
|
||||
smodel.calc_params(peaks, weight, 3.0f);
|
||||
|
||||
|
||||
//update shape
|
||||
pts = smodel.calc_shape();
|
||||
|
||||
//check for convergence
|
||||
float v = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
using (MatOfPoint tmpMat = new MatOfPoint (new Point (pts [i].x - pts_old [i].x, pts [i].y - pts_old [i].y)))
|
||||
{
|
||||
v += (float)Core.norm(tmpMat);
|
||||
}
|
||||
}
|
||||
if (v < ftol)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
pts_old = pts;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pts;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using OpenCVForUnity;
|
||||
|
||||
namespace OpenCVFaceTracker
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Face tracker parameters.
|
||||
/// Code is the rewrite of https://github.com/MasteringOpenCV/code/tree/master/Chapter6_NonRigidFaceTracking using the “OpenCV for Unity”.
|
||||
/// </summary>
|
||||
public class FaceTrackerParams
|
||||
{
|
||||
|
||||
public List<OpenCVForUnity.Size> ssize; //search region size/level
|
||||
public bool robust; //use robust fitting?
|
||||
public int itol; //maximum number of iterations to try
|
||||
public double ftol; //convergence tolerance
|
||||
// public float scaleFactor; //OpenCV Cascade detector parameters
|
||||
// public int minNeighbours; //...
|
||||
// public OpenCVForUnity.Size minSize;
|
||||
|
||||
public FaceTrackerParams(bool robust = false, int itol = 20, double ftol = 1e-3, List<OpenCVForUnity.Size> ssize = null)
|
||||
{
|
||||
if (ssize == null)
|
||||
{
|
||||
this.ssize = new List<Size>();
|
||||
this.ssize.Add(new OpenCVForUnity.Size(21, 21));
|
||||
this.ssize.Add(new OpenCVForUnity.Size(11, 11));
|
||||
this.ssize.Add(new OpenCVForUnity.Size(5, 5));
|
||||
} else
|
||||
{
|
||||
this.ssize = ssize;
|
||||
}
|
||||
|
||||
this.robust = robust;
|
||||
this.itol = itol;
|
||||
this.ftol = ftol;
|
||||
// scaleFactor = 1.1f;
|
||||
// minNeighbours = 2;
|
||||
// minSize = new OpenCVForUnity.Size (30, 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
using OpenCVForUnity;
|
||||
|
||||
namespace OpenCVFaceTracker
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Patch model.
|
||||
/// Code is the rewrite of https://github.com/MasteringOpenCV/code/tree/master/Chapter6_NonRigidFaceTracking using the “OpenCV for Unity”.
|
||||
/// </summary>
|
||||
public class PatchModel
|
||||
{
|
||||
|
||||
Mat P; //normalised patch
|
||||
|
||||
public PatchModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//size of patch model
|
||||
public Size patch_size()
|
||||
{
|
||||
return P.size();
|
||||
}
|
||||
|
||||
Mat convert_image(Mat im)
|
||||
{
|
||||
Mat I = null;
|
||||
if (im.channels() == 1)
|
||||
{
|
||||
if (im.type() != CvType.CV_32F)
|
||||
{
|
||||
I = new Mat();
|
||||
im.convertTo(I, CvType.CV_32F);
|
||||
} else
|
||||
{
|
||||
I = im;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (im.channels() == 3)
|
||||
{
|
||||
Mat img = new Mat();
|
||||
Imgproc.cvtColor(im, img, Imgproc.COLOR_RGBA2GRAY);
|
||||
if (img.type() != CvType.CV_32F)
|
||||
{
|
||||
I = new Mat();
|
||||
img.convertTo(I, CvType.CV_32F);
|
||||
} else
|
||||
{
|
||||
I = img;
|
||||
}
|
||||
} else
|
||||
{
|
||||
Debug.Log("Unsupported image type!");
|
||||
}
|
||||
}
|
||||
Core.add(I, new Scalar(1.0), I);
|
||||
Core.log(I, I);
|
||||
return I;
|
||||
}
|
||||
|
||||
public Mat calc_response(Mat im, bool sum2one)
|
||||
{
|
||||
Mat I = convert_image(im);
|
||||
Mat res = new Mat();
|
||||
|
||||
Imgproc.matchTemplate(I, P, res, Imgproc.TM_CCOEFF_NORMED);
|
||||
if (sum2one)
|
||||
{
|
||||
Core.normalize(res, res, 0, 1, Core.NORM_MINMAX);
|
||||
|
||||
Core.divide(res, new Scalar(Core.sumElems(res).val [0]), res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public void read(object root_json)
|
||||
{
|
||||
IDictionary pmodel_json = (IDictionary)root_json;
|
||||
|
||||
IDictionary P_json = (IDictionary)pmodel_json ["P"];
|
||||
P = new Mat((int)(long)P_json ["rows"], (int)(long)P_json ["cols"], CvType.CV_32F);
|
||||
// Debug.Log ("P " + P.ToString ());
|
||||
|
||||
IList P_data_json = (IList)P_json ["data"];
|
||||
float[] P_data = new float[P.rows() * P.cols()];
|
||||
for (int i = 0; i < P_data_json.Count; i++)
|
||||
{
|
||||
P_data [i] = (float)(double)P_data_json [i];
|
||||
}
|
||||
Utils.copyToMat(P_data, P);
|
||||
// Debug.Log ("P dump " + P.dump ());
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System;
|
||||
|
||||
using OpenCVForUnity;
|
||||
|
||||
namespace OpenCVFaceTracker
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Patch models.
|
||||
/// Code is the rewrite of https://github.com/MasteringOpenCV/code/tree/master/Chapter6_NonRigidFaceTracking using the “OpenCV for Unity”.
|
||||
/// </summary>
|
||||
public class PatchModels
|
||||
{
|
||||
|
||||
public Mat reference; //reference shape
|
||||
public IList<PatchModel> patches; //patch models
|
||||
|
||||
public PatchModels()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//number of patches
|
||||
public int n_patches()
|
||||
{
|
||||
return patches.Count;
|
||||
}
|
||||
|
||||
public Point[] calc_peaks(Mat im,
|
||||
Point[] points,
|
||||
OpenCVForUnity.Size ssize)
|
||||
{
|
||||
int n = points.Length;
|
||||
// Debug.Log ("n == int(patches.size()) " + patches.Count);
|
||||
using (Mat pt = (new MatOfPoint2f (points)).reshape (1, 2 * n))
|
||||
using (Mat S = calc_simil (pt))
|
||||
using (Mat Si = inv_simil (S))
|
||||
{
|
||||
|
||||
float[] pt_float = new float[pt.total()];
|
||||
Utils.copyFromMat<float>(pt, pt_float);
|
||||
int pt_cols = pt.cols();
|
||||
|
||||
float[] S_float = new float[S.total()];
|
||||
Utils.copyFromMat<float>(S, S_float);
|
||||
int S_cols = S.cols();
|
||||
|
||||
float[] A_float = new float[2 * 3];
|
||||
|
||||
Point[] pts = apply_simil(Si, points);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
|
||||
OpenCVForUnity.Size wsize = new OpenCVForUnity.Size(ssize.width + patches [i].patch_size().width, ssize.height + patches [i].patch_size().height);
|
||||
using (Mat A = new Mat (2, 3, CvType.CV_32F))
|
||||
{
|
||||
|
||||
Utils.copyFromMat<float>(A, A_float);
|
||||
int A_cols = A.cols();
|
||||
|
||||
A_float [0] = S_float [0];
|
||||
A_float [1] = S_float [1];
|
||||
A_float [1 * A_cols] = S_float [1 * S_cols];
|
||||
A_float [(1 * A_cols) + 1] = S_float [(1 * S_cols) + 1];
|
||||
A_float [2] = (float)(pt_float [(2 * pt_cols) * i] -
|
||||
(A_float [0] * (wsize.width - 1) / 2 + A_float [1] * (wsize.height - 1) / 2));
|
||||
A_float [(1 * A_cols) + 2] = (float)(pt_float [((2 * pt_cols) * i) + 1] -
|
||||
(A_float [1 * A_cols] * (wsize.width - 1) / 2 + A_float [(1 * A_cols) + 1] * (wsize.height - 1) / 2));
|
||||
|
||||
Utils.copyToMat(A_float, A);
|
||||
|
||||
using (Mat I = new Mat ())
|
||||
{
|
||||
Imgproc.warpAffine(im, I, A, wsize, Imgproc.INTER_LINEAR + Imgproc.WARP_INVERSE_MAP);
|
||||
using (Mat R = patches [i].calc_response (I, false))
|
||||
{
|
||||
|
||||
Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(R);
|
||||
pts [i].x = pts [i].x + minMaxLocResult.maxLoc.x - 0.5 * ssize.width;
|
||||
pts [i].y = pts [i].y + minMaxLocResult.maxLoc.y - 0.5 * ssize.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return apply_simil(S, pts);
|
||||
}
|
||||
}
|
||||
|
||||
Point[] apply_simil(Mat S, Point[] points)
|
||||
{
|
||||
|
||||
float[] S_float = new float[S.total()];
|
||||
Utils.copyFromMat<float>(S, S_float);
|
||||
int S_cols = S.cols();
|
||||
|
||||
int n = points.Length;
|
||||
Point[] p = new Point[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
p [i] = new Point();
|
||||
p [i].x = S_float [0] * points [i].x + S_float [1] * points [i].y + S_float [2];
|
||||
p [i].y = S_float [1 * S_cols] * points [i].x + S_float [(1 * S_cols) + 1] * points [i].y + S_float [(1 * S_cols) + 2];
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
Mat inv_simil(Mat S)
|
||||
{
|
||||
|
||||
float[] S_float = new float[S.total()];
|
||||
Utils.copyFromMat<float>(S, S_float);
|
||||
int S_cols = S.cols();
|
||||
|
||||
Mat Si = new Mat(2, 3, CvType.CV_32F);
|
||||
float d = S_float [0] * S_float [(1 * S_cols) + 1] - S_float [1 * S_cols] * S_float [1];
|
||||
|
||||
float[] Si_float = new float[Si.total()];
|
||||
Utils.copyFromMat<float>(Si, Si_float);
|
||||
int Si_cols = Si.cols();
|
||||
|
||||
Si_float [0] = S_float [(1 * S_cols) + 1] / d;
|
||||
Si_float [1] = -S_float [1] / d;
|
||||
Si_float [(1 * Si_cols) + 1] = S_float [0] / d;
|
||||
Si_float [1 * Si_cols] = -S_float [1 * S_cols] / d;
|
||||
|
||||
Utils.copyToMat(Si_float, Si);
|
||||
|
||||
Mat Ri = new Mat(Si, new OpenCVForUnity.Rect(0, 0, 2, 2));
|
||||
|
||||
|
||||
Mat negaRi = new Mat();
|
||||
Core.multiply(Ri, new Scalar(-1), negaRi);
|
||||
Mat t = new Mat();
|
||||
Core.gemm(negaRi, S.col(2), 1, new Mat(negaRi.rows(), negaRi.cols(), negaRi.type()), 0, t);
|
||||
|
||||
Mat St = Si.col(2);
|
||||
t.copyTo(St);
|
||||
|
||||
return Si;
|
||||
}
|
||||
|
||||
Mat calc_simil(Mat pts)
|
||||
{
|
||||
float[] pts_float = new float[pts.total()];
|
||||
Utils.copyFromMat<float>(pts, pts_float);
|
||||
int pts_cols = pts.cols();
|
||||
|
||||
//compute translation
|
||||
int n = pts.rows() / 2;
|
||||
float mx = 0, my = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
mx += pts_float [(2 * pts_cols) * i];
|
||||
my += pts_float [((2 * pts_cols) * i) + 1];
|
||||
}
|
||||
using (Mat p = new Mat (2 * n, 1, CvType.CV_32F))
|
||||
{
|
||||
|
||||
float[] p_float = new float[p.total()];
|
||||
Utils.copyFromMat<float>(p, p_float);
|
||||
int p_cols = p.cols();
|
||||
|
||||
mx /= n;
|
||||
my /= n;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
p_float [(2 * p_cols) * i] = pts_float [(2 * pts_cols) * i] - mx;
|
||||
p_float [((2 * p_cols) * i) + 1] = pts_float [((2 * pts_cols) * i) + 1] - my;
|
||||
}
|
||||
Utils.copyToMat(p_float, p);
|
||||
|
||||
//compute rotation and scale
|
||||
float[] reference_float = new float[reference.total()];
|
||||
Utils.copyFromMat<float>(reference, reference_float);
|
||||
int reference_cols = reference.cols();
|
||||
|
||||
float a = 0, b = 0, c = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
a += reference_float [(2 * reference_cols) * i] * reference_float [(2 * reference_cols) * i] +
|
||||
reference_float [((2 * reference_cols) * i) + 1] * reference_float [((2 * reference_cols) * i) + 1];
|
||||
b += reference_float [(2 * reference_cols) * i] * p_float [(2 * p_cols) * i] +
|
||||
reference_float [((2 * reference_cols) * i) + 1] * p_float [((2 * p_cols) * i) + 1];
|
||||
c += reference_float [(2 * reference_cols) * i] * p_float [((2 * p_cols) * i) + 1] -
|
||||
reference_float [((2 * reference_cols) * i) + 1] * p_float [(2 * p_cols) * i];
|
||||
}
|
||||
b /= a;
|
||||
c /= a;
|
||||
float scale = (float)Math.Sqrt(b * b + c * c), theta = (float)Math.Atan2(c, b);
|
||||
float sc = scale * (float)Math.Cos(theta), ss = scale * (float)Math.Sin(theta);
|
||||
|
||||
Mat returnMat = new Mat(2, 3, CvType.CV_32F);
|
||||
returnMat.put(0, 0, sc, -ss, mx, ss, sc, my);
|
||||
|
||||
return returnMat;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void read(object root_json)
|
||||
{
|
||||
IDictionary pmodels_json = (IDictionary)root_json;
|
||||
|
||||
IDictionary reference_json = (IDictionary)pmodels_json ["reference"];
|
||||
|
||||
reference = new Mat((int)(long)reference_json ["rows"], (int)(long)reference_json ["cols"], CvType.CV_32F);
|
||||
// Debug.Log ("reference " + reference.ToString ());
|
||||
|
||||
IList data_json = (IList)reference_json ["data"];
|
||||
float[] data = new float[reference.rows() * reference.cols()];
|
||||
int count = data_json.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
data [i] = (float)(double)data_json [i];
|
||||
}
|
||||
Utils.copyToMat(data, reference);
|
||||
// Debug.Log ("reference dump " + reference.dump ());
|
||||
|
||||
|
||||
int n = (int)(long)pmodels_json ["n_patches"];
|
||||
patches = new List<PatchModel>(n);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
PatchModel patchModel = new PatchModel();
|
||||
patchModel.read(pmodels_json ["patch " + i]);
|
||||
|
||||
patches.Add(patchModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
using System;
|
||||
|
||||
using OpenCVForUnity;
|
||||
|
||||
namespace OpenCVFaceTracker
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Shape model.
|
||||
/// Code is the rewrite of https://github.com/MasteringOpenCV/code/tree/master/Chapter6_NonRigidFaceTracking using the “OpenCV for Unity”.
|
||||
/// </summary>
|
||||
public class ShapeModel
|
||||
{
|
||||
|
||||
public Mat p; //parameter vector (kx1) CV_32F
|
||||
public Mat V; //shape basis (2nxk) CV_32F
|
||||
public Mat e; //parameter variance (kx1) CV_32F
|
||||
public Mat C; //connectivity (cx2) CV_32S
|
||||
|
||||
|
||||
public ShapeModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public int npts()
|
||||
{
|
||||
//number of points in shape model
|
||||
return V.rows() / 2;
|
||||
}
|
||||
|
||||
public void calc_params(Point[] pts, Mat weight, float c_factor)
|
||||
{
|
||||
int n = pts.Length;
|
||||
// assert(V.rows == 2*n);
|
||||
// Debug.Log ("V.rows == 2*n " + V.rows () + " " + 2 * n);
|
||||
|
||||
using (Mat s = (new MatOfPoint2f (pts)).reshape (1, 2 * n))
|
||||
{ //point set to vector format
|
||||
|
||||
if (weight.empty())
|
||||
{
|
||||
Core.gemm(V.t(), s, 1, new Mat(), 0, p); //simple projection
|
||||
|
||||
} else
|
||||
{ //scaled projection
|
||||
if (weight.rows() != n)
|
||||
{
|
||||
Debug.Log("Invalid weighting matrix");
|
||||
}
|
||||
|
||||
float[] weight_float = new float[weight.total()];
|
||||
Utils.copyFromMat<float>(weight, weight_float);
|
||||
int weight_cols = weight.cols();
|
||||
|
||||
int K = V.cols();
|
||||
using (Mat H = Mat.zeros (K, K, CvType.CV_32F))
|
||||
using (Mat g = Mat.zeros (K, 1, CvType.CV_32F))
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
using (Mat v = new Mat (V, new OpenCVForUnity.Rect (0, 2 * i, K, 2)))
|
||||
using (Mat tmpMat1 = new Mat ())
|
||||
using (Mat tmpMat2 = new Mat ())
|
||||
using (Mat tmpMat3 = new Mat ())
|
||||
{
|
||||
|
||||
float w = weight_float [i * weight_cols];
|
||||
|
||||
Core.multiply(v.t(), new Scalar(w), tmpMat1);
|
||||
|
||||
Core.gemm(tmpMat1, v, 1, new Mat(), 0, tmpMat2);
|
||||
Core.add(H, tmpMat2, H);
|
||||
|
||||
Core.gemm(tmpMat1, new MatOfPoint2f(pts [i]).reshape(1, 2), 1, new Mat(), 0, tmpMat3);
|
||||
Core.add(g, tmpMat3, g);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Core.solve(H, g, p, Core.DECOMP_SVD);
|
||||
}
|
||||
}
|
||||
}
|
||||
clamp(c_factor); //clamp resulting parameters
|
||||
}
|
||||
|
||||
public Point[] calc_shape()
|
||||
{
|
||||
using (Mat s = new Mat ())
|
||||
{
|
||||
Core.gemm(V, p, 1, new Mat(), 0, s);
|
||||
|
||||
float[] s_float = new float[s.total()];
|
||||
Utils.copyFromMat<float>(s, s_float);
|
||||
int s_cols = s.cols();
|
||||
|
||||
int n = s.rows() / 2;
|
||||
Point[] pts = new Point[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
pts [i] = new Point(s_float [(2 * s_cols) * i], s_float [((2 * s_cols) * i) + 1]);
|
||||
}
|
||||
|
||||
return pts;
|
||||
}
|
||||
}
|
||||
|
||||
void clamp(float c)
|
||||
{
|
||||
|
||||
float[] p_float = new float[p.total()];
|
||||
Utils.copyFromMat<float>(p, p_float);
|
||||
int p_cols = p.cols();
|
||||
|
||||
float[] e_float = new float[e.total()];
|
||||
Utils.copyFromMat<float>(e, e_float);
|
||||
int e_cols = e.cols();
|
||||
|
||||
double scale = p_float [0];
|
||||
int rows = e.rows();
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
if (e_float [i * e_cols] < 0)
|
||||
continue;
|
||||
float v = c * (float)Math.Sqrt(e_float [i * e_cols]);
|
||||
if (Math.Abs(p_float [i * p_cols] / scale) > v)
|
||||
{
|
||||
if (p_float [i * p_cols] > 0)
|
||||
{
|
||||
p_float [i * p_cols] = (float)(v * scale);
|
||||
} else
|
||||
{
|
||||
p_float [i * p_cols] = (float)(-v * scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
Utils.copyToMat(p_float, p);
|
||||
}
|
||||
|
||||
public void read(object root_json)
|
||||
{
|
||||
IDictionary smodel_json = (IDictionary)root_json;
|
||||
|
||||
IDictionary V_json = (IDictionary)smodel_json ["V"];
|
||||
V = new Mat((int)(long)V_json ["rows"], (int)(long)V_json ["cols"], CvType.CV_32F);
|
||||
// Debug.Log ("V " + V.ToString ());
|
||||
|
||||
IList V_data_json = (IList)V_json ["data"];
|
||||
float[] V_data = new float[V.rows() * V.cols()];
|
||||
for (int i = 0; i < V_data_json.Count; i++)
|
||||
{
|
||||
V_data [i] = (float)(double)V_data_json [i];
|
||||
}
|
||||
Utils.copyToMat(V_data, V);
|
||||
// Debug.Log ("V dump " + V.dump ());
|
||||
|
||||
|
||||
|
||||
IDictionary e_json = (IDictionary)smodel_json ["e"];
|
||||
e = new Mat((int)(long)e_json ["rows"], (int)(long)e_json ["cols"], CvType.CV_32F);
|
||||
// Debug.Log ("e " + e.ToString ());
|
||||
|
||||
IList e_data_json = (IList)e_json ["data"];
|
||||
float[] e_data = new float[e.rows() * e.cols()];
|
||||
for (int i = 0; i < e_data_json.Count; i++)
|
||||
{
|
||||
e_data [i] = (float)(double)e_data_json [i];
|
||||
}
|
||||
Utils.copyToMat(e_data, e);
|
||||
// Debug.Log ("e dump " + e.dump ());
|
||||
|
||||
|
||||
|
||||
IDictionary C_json = (IDictionary)smodel_json ["C"];
|
||||
C = new Mat((int)(long)C_json ["rows"], (int)(long)C_json ["cols"], CvType.CV_32S);
|
||||
// Debug.Log ("C " + C.ToString ());
|
||||
|
||||
IList C_data_json = (IList)C_json ["data"];
|
||||
int[] C_data = new int[C.rows() * C.cols()];
|
||||
for (int i = 0; i < C_data_json.Count; i++)
|
||||
{
|
||||
C_data [i] = (int)(long)C_data_json [i];
|
||||
}
|
||||
Utils.copyToMat(C_data, C);
|
||||
// Debug.Log ("C dump " + C.dump ());
|
||||
|
||||
|
||||
|
||||
p = Mat.zeros(e.rows(), 1, CvType.CV_32F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,13 +2,14 @@
|
|||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 3
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: axes_x_material
|
||||
m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: []
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9c7da247ee667064eb6f3b9038888e52
|
||||
timeCreated: 1479122948
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -2,13 +2,14 @@
|
|||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 3
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: axes_y_material
|
||||
m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: []
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 47a655d401841fa449fad13a4aaf5fe9
|
||||
timeCreated: 1479122948
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -2,13 +2,14 @@
|
|||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 3
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: axes_z_material
|
||||
m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: []
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5387dd0eaea36984ca50323a24743fe5
|
||||
timeCreated: 1479122948
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,29 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: head_material
|
||||
m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
data:
|
||||
first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats: {}
|
||||
m_Colors:
|
||||
data:
|
||||
first:
|
||||
name: _Color
|
||||
second: {r: .800000012, g: 0, b: 0, a: .458823532}
|
|
@ -0,0 +1,29 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: quad_material
|
||||
m_Shader: {fileID: 10750, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
data:
|
||||
first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 2800000, guid: 149ff4a24e94f2648b70037fdd711cda, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats: {}
|
||||
m_Colors:
|
||||
data:
|
||||
first:
|
||||
name: _Color
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
|
@ -0,0 +1,29 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: eff_heart_1
|
||||
m_Shader: {fileID: 10720, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
data:
|
||||
first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 2800000, guid: 99f812eaed1274ca6a538812c7494cf8, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats: {}
|
||||
m_Colors:
|
||||
data:
|
||||
first:
|
||||
name: _Color
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
До Ширина: | Высота: | Размер: 30 KiB После Ширина: | Высота: | Размер: 30 KiB |
|
@ -0,0 +1,87 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &100000
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 4: {fileID: 400000}
|
||||
- 33: {fileID: 3300000}
|
||||
- 136: {fileID: 13600000}
|
||||
- 23: {fileID: 2300000}
|
||||
m_Layer: 5
|
||||
m_Name: Axes_X
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &400000
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_LocalRotation: {x: 0, y: 0, z: .707106829, w: .707106829}
|
||||
m_LocalPosition: {x: 25, y: 0, z: 0}
|
||||
m_LocalScale: {x: 10, y: 25, z: 10}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
--- !u!23 &2300000
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 9c7da247ee667064eb6f3b9038888e52, type: 2}
|
||||
m_SubsetIndices:
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_UseLightProbes: 0
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 0
|
||||
m_ImportantGI: 0
|
||||
m_AutoUVMaxDistance: .5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!33 &3300000
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!136 &13600000
|
||||
CapsuleCollider:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
m_Radius: .5
|
||||
m_Height: 2
|
||||
m_Direction: 1
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!1001 &100100000
|
||||
Prefab:
|
||||
m_ObjectHideFlags: 1
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications: []
|
||||
m_RemovedComponents: []
|
||||
m_ParentPrefab: {fileID: 0}
|
||||
m_RootGameObject: {fileID: 100000}
|
||||
m_IsPrefabParent: 1
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bfb641200606a7547866e6009a23ba7d
|
||||
timeCreated: 1479122901
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,87 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &100000
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 4: {fileID: 400000}
|
||||
- 33: {fileID: 3300000}
|
||||
- 136: {fileID: 13600000}
|
||||
- 23: {fileID: 2300000}
|
||||
m_Layer: 5
|
||||
m_Name: Axes_Y
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &400000
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 25, z: 0}
|
||||
m_LocalScale: {x: 10, y: 25, z: 10}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
--- !u!23 &2300000
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 47a655d401841fa449fad13a4aaf5fe9, type: 2}
|
||||
m_SubsetIndices:
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_UseLightProbes: 0
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 0
|
||||
m_ImportantGI: 0
|
||||
m_AutoUVMaxDistance: .5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!33 &3300000
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!136 &13600000
|
||||
CapsuleCollider:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
m_Radius: .5
|
||||
m_Height: 2
|
||||
m_Direction: 1
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!1001 &100100000
|
||||
Prefab:
|
||||
m_ObjectHideFlags: 1
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications: []
|
||||
m_RemovedComponents: []
|
||||
m_ParentPrefab: {fileID: 0}
|
||||
m_RootGameObject: {fileID: 100000}
|
||||
m_IsPrefabParent: 1
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bca5770cdbc530544b4d0a55934308e5
|
||||
timeCreated: 1479122901
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,87 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &100000
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 4: {fileID: 400000}
|
||||
- 33: {fileID: 3300000}
|
||||
- 136: {fileID: 13600000}
|
||||
- 23: {fileID: 2300000}
|
||||
m_Layer: 5
|
||||
m_Name: Axes_Z
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &400000
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_LocalRotation: {x: .707106829, y: 0, z: 0, w: .707106829}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 25}
|
||||
m_LocalScale: {x: 10, y: 25, z: 10}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
--- !u!23 &2300000
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 5387dd0eaea36984ca50323a24743fe5, type: 2}
|
||||
m_SubsetIndices:
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_UseLightProbes: 0
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 0
|
||||
m_ImportantGI: 0
|
||||
m_AutoUVMaxDistance: .5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!33 &3300000
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!136 &13600000
|
||||
CapsuleCollider:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 100000}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
m_Radius: .5
|
||||
m_Height: 2
|
||||
m_Direction: 1
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!1001 &100100000
|
||||
Prefab:
|
||||
m_ObjectHideFlags: 1
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications: []
|
||||
m_RemovedComponents: []
|
||||
m_ParentPrefab: {fileID: 0}
|
||||
m_RootGameObject: {fileID: 100000}
|
||||
m_IsPrefabParent: 1
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eb982187efa15764e90795cda7466bd3
|
||||
timeCreated: 1479122901
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7f6105b1b5a1d5645b82d2ce05e255e4
|
||||
folderAsset: yes
|
||||
timeCreated: 1478828427
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,145 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: unnamed
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_CustomRenderQueue: -1
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
data:
|
||||
first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
data:
|
||||
first:
|
||||
name: _BumpMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
data:
|
||||
first:
|
||||
name: _DetailNormalMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
data:
|
||||
first:
|
||||
name: _ParallaxMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
data:
|
||||
first:
|
||||
name: _OcclusionMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
data:
|
||||
first:
|
||||
name: _EmissionMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
data:
|
||||
first:
|
||||
name: _DetailMask
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
data:
|
||||
first:
|
||||
name: _DetailAlbedoMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
data:
|
||||
first:
|
||||
name: _MetallicGlossMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
data:
|
||||
first:
|
||||
name: _Cutoff
|
||||
second: .5
|
||||
data:
|
||||
first:
|
||||
name: _SrcBlend
|
||||
second: 1
|
||||
data:
|
||||
first:
|
||||
name: _DstBlend
|
||||
second: 0
|
||||
data:
|
||||
first:
|
||||
name: _Parallax
|
||||
second: .0199999996
|
||||
data:
|
||||
first:
|
||||
name: _ZWrite
|
||||
second: 1
|
||||
data:
|
||||
first:
|
||||
name: _Glossiness
|
||||
second: .5
|
||||
data:
|
||||
first:
|
||||
name: _BumpScale
|
||||
second: 1
|
||||
data:
|
||||
first:
|
||||
name: _OcclusionStrength
|
||||
second: 1
|
||||
data:
|
||||
first:
|
||||
name: _DetailNormalMapScale
|
||||
second: 1
|
||||
data:
|
||||
first:
|
||||
name: _UVSec
|
||||
second: 0
|
||||
data:
|
||||
first:
|
||||
name: _EmissionScaleUI
|
||||
second: 0
|
||||
data:
|
||||
first:
|
||||
name: _Mode
|
||||
second: 0
|
||||
data:
|
||||
first:
|
||||
name: _Metallic
|
||||
second: 0
|
||||
m_Colors:
|
||||
data:
|
||||
first:
|
||||
name: _EmissionColor
|
||||
second: {r: 0, g: 0, b: 0, a: 1}
|
||||
data:
|
||||
first:
|
||||
name: _Color
|
||||
second: {r: .800000012, g: .800000012, b: .800000012, a: 1}
|
||||
data:
|
||||
first:
|
||||
name: _EmissionColorUI
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ee07e9811c88af24cba02bd598ba9cc4
|
||||
timeCreated: 1478828427
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
После Ширина: | Высота: | Размер: 3.8 KiB |
|
@ -0,0 +1,55 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 149ff4a24e94f2648b70037fdd711cda
|
||||
timeCreated: 1479991564
|
||||
licenseType: Pro
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
linearTexture: 0
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 512
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 0
|
||||
textureType: -1
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
До Ширина: | Высота: | Размер: 1.4 MiB После Ширина: | Высота: | Размер: 1.4 MiB |
|
@ -0,0 +1,694 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
SceneSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PVSData:
|
||||
m_PVSObjectsArray: []
|
||||
m_PVSPortalsArray: []
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: .25
|
||||
backfaceThreshold: 100
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 6
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: .5, g: .5, b: .5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: .00999999978
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: .200000003, g: .200000003, b: .200000003, a: 1}
|
||||
m_AmbientEquatorColor: {r: .200000003, g: .200000003, b: .200000003, a: 1}
|
||||
m_AmbientGroundColor: {r: .200000003, g: .200000003, b: .200000003, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 3
|
||||
m_SkyboxMaterial: {fileID: 0}
|
||||
m_HaloStrength: .5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
--- !u!127 &3
|
||||
LevelGameManager:
|
||||
m_ObjectHideFlags: 0
|
||||
--- !u!157 &4
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 5
|
||||
m_GIWorkflowMode: 1
|
||||
m_LightmapsMode: 1
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_TemporalCoherenceThreshold: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 3
|
||||
m_Resolution: 1
|
||||
m_BakeResolution: 50
|
||||
m_TextureWidth: 1024
|
||||
m_TextureHeight: 1024
|
||||
m_AOMaxDistance: 1
|
||||
m_Padding: 2
|
||||
m_CompAOExponent: 0
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_TextureCompression: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherRayCount: 1024
|
||||
m_LightmapSnapshot: {fileID: 0}
|
||||
m_RuntimeCPUUsage: 25
|
||||
--- !u!196 &5
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
agentRadius: .5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: .400000006
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
accuratePlacement: 0
|
||||
minRegionArea: 2
|
||||
cellSize: .166666657
|
||||
manualCellSize: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &446087106
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 100004, guid: e4ed316126173e54da8ebe67c2421b33, type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 224: {fileID: 446087107}
|
||||
- 222: {fileID: 446087111}
|
||||
- 114: {fileID: 446087110}
|
||||
- 114: {fileID: 446087109}
|
||||
- 114: {fileID: 446087108}
|
||||
m_Layer: 5
|
||||
m_Name: BackButton
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &446087107
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 22400004, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 446087106}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 1968934797}
|
||||
m_Father: {fileID: 1245564527}
|
||||
m_RootOrder: 0
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: .5, y: .5}
|
||||
--- !u!114 &446087108
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400006, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 446087106}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 1679637790, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IgnoreLayout: 0
|
||||
m_MinWidth: -1
|
||||
m_MinHeight: -1
|
||||
m_PreferredWidth: 160
|
||||
m_PreferredHeight: 40
|
||||
m_FlexibleWidth: -1
|
||||
m_FlexibleHeight: -1
|
||||
--- !u!114 &446087109
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400008, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 446087106}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: .960784316, g: .960784316, b: .960784316, a: 1}
|
||||
m_PressedColor: {r: .784313738, g: .784313738, b: .784313738, a: 1}
|
||||
m_DisabledColor: {r: .784313738, g: .784313738, b: .784313738, a: .501960814}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: .100000001
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 446087110}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 2099749953}
|
||||
m_MethodName: OnBackButton
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine, Version=0.0.0.0,
|
||||
Culture=neutral, PublicKeyToken=null
|
||||
m_IntArgument: 0
|
||||
m_FloatArgument: 0
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0,
|
||||
Culture=neutral, PublicKeyToken=null
|
||||
--- !u!114 &446087110
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400010, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 446087106}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
--- !u!222 &446087111
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 22200002, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 446087106}
|
||||
--- !u!1 &450146740
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 100002, guid: e4ed316126173e54da8ebe67c2421b33, type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 224: {fileID: 450146744}
|
||||
- 223: {fileID: 450146743}
|
||||
- 114: {fileID: 450146742}
|
||||
- 114: {fileID: 450146741}
|
||||
m_Layer: 5
|
||||
m_Name: Canvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &450146741
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400002, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 450146740}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IgnoreReversedGraphics: 1
|
||||
m_BlockingObjects: 0
|
||||
m_BlockingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
--- !u!114 &450146742
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400004, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 450146740}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 1
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 800, y: 600}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
--- !u!223 &450146743
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 22300000, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 450146740}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_RenderMode: 0
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!224 &450146744
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 22400002, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 450146740}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_Children:
|
||||
- {fileID: 1245564527}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!1 &553942307
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 100000, guid: 1ccccd5701fc6ee48964a3c728b8ab62, type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 4: {fileID: 553942311}
|
||||
- 114: {fileID: 553942310}
|
||||
- 114: {fileID: 553942309}
|
||||
- 114: {fileID: 553942308}
|
||||
m_Layer: 0
|
||||
m_Name: EventSystem
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &553942308
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400000, guid: 1ccccd5701fc6ee48964a3c728b8ab62,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 553942307}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_AllowActivationOnStandalone: 0
|
||||
--- !u!114 &553942309
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400002, guid: 1ccccd5701fc6ee48964a3c728b8ab62,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 553942307}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_HorizontalAxis: Horizontal
|
||||
m_VerticalAxis: Vertical
|
||||
m_SubmitButton: Submit
|
||||
m_CancelButton: Cancel
|
||||
m_InputActionsPerSecond: 10
|
||||
m_AllowActivationOnMobileDevice: 0
|
||||
--- !u!114 &553942310
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400004, guid: 1ccccd5701fc6ee48964a3c728b8ab62,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 553942307}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_FirstSelected: {fileID: 0}
|
||||
m_sendNavigationEvents: 1
|
||||
m_DragThreshold: 5
|
||||
--- !u!4 &553942311
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 400000, guid: 1ccccd5701fc6ee48964a3c728b8ab62, type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 553942307}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 3
|
||||
--- !u!1 &1245564526
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 100006, guid: e4ed316126173e54da8ebe67c2421b33, type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 224: {fileID: 1245564527}
|
||||
- 114: {fileID: 1245564528}
|
||||
m_Layer: 5
|
||||
m_Name: Menu
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1245564527
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 22400006, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1245564526}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 446087107}
|
||||
m_Father: {fileID: 450146744}
|
||||
m_RootOrder: 0
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: .5, y: .5}
|
||||
--- !u!114 &1245564528
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400012, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1245564526}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 1297475563, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Padding:
|
||||
m_Left: 10
|
||||
m_Right: 10
|
||||
m_Top: 10
|
||||
m_Bottom: 10
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: 10
|
||||
m_ChildForceExpandWidth: 0
|
||||
m_ChildForceExpandHeight: 0
|
||||
--- !u!1 &1319493345
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 4: {fileID: 1319493351}
|
||||
- 20: {fileID: 1319493350}
|
||||
- 92: {fileID: 1319493349}
|
||||
- 124: {fileID: 1319493348}
|
||||
- 81: {fileID: 1319493347}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &1319493347
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1319493345}
|
||||
m_Enabled: 1
|
||||
--- !u!124 &1319493348
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1319493345}
|
||||
m_Enabled: 1
|
||||
--- !u!92 &1319493349
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1319493345}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &1319493350
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1319493345}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: .192156866, g: .301960796, b: .474509805, a: .0196078438}
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: .300000012
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 1
|
||||
orthographic size: 240
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_HDR: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: .0219999999
|
||||
--- !u!4 &1319493351
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1319493345}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
--- !u!1 &1968934796
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 100008, guid: e4ed316126173e54da8ebe67c2421b33, type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 224: {fileID: 1968934797}
|
||||
- 222: {fileID: 1968934799}
|
||||
- 114: {fileID: 1968934798}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1968934797
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 22400008, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1968934796}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 446087107}
|
||||
m_RootOrder: 0
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: .5, y: .5}
|
||||
--- !u!114 &1968934798
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 11400014, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1968934796}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: .195999995, g: .195999995, b: .195999995, a: 1}
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 10
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 4
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: Back
|
||||
--- !u!222 &1968934799
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 22200004, guid: e4ed316126173e54da8ebe67c2421b33,
|
||||
type: 2}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1968934796}
|
||||
--- !u!1 &2099749952
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 4: {fileID: 2099749957}
|
||||
- 33: {fileID: 2099749956}
|
||||
- 64: {fileID: 2099749955}
|
||||
- 23: {fileID: 2099749954}
|
||||
- 114: {fileID: 2099749953}
|
||||
m_Layer: 0
|
||||
m_Name: Quad
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &2099749953
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 2099749952}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2b5f56412d33c3e499e04f152433fd5b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
imgTexture: {fileID: 2800000, guid: 3abc257791f75f1459d7c9a6dff35cf1, type: 3}
|
||||
--- !u!23 &2099749954
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 2099749952}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 2fe89ad658086d24f8fe283057df260d, type: 2}
|
||||
m_SubsetIndices:
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_UseLightProbes: 0
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 0
|
||||
m_ImportantGI: 0
|
||||
m_AutoUVMaxDistance: .5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!64 &2099749955
|
||||
MeshCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 2099749952}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_Convex: 0
|
||||
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!33 &2099749956
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 2099749952}
|
||||
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!4 &2099749957
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 2099749952}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 640, y: 480, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
|
@ -0,0 +1,860 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.UI;
|
||||
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
using UnityEngine.SceneManagement;
|
||||
#endif
|
||||
using OpenCVForUnity;
|
||||
using OpenCVFaceTracker;
|
||||
|
||||
namespace FaceTrackerExample
|
||||
{
|
||||
/// <summary>
|
||||
/// Face tracker AR example.
|
||||
/// This Example was referring to http://www.morethantechnical.com/2012/10/17/head-pose-estimation-with-opencv-opengl-revisited-w-code/
|
||||
/// and use effect asset from http://ktk-kumamoto.hatenablog.com/entry/2014/09/14/092400
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(WebCamTextureToMatHelper))]
|
||||
public class FaceTrackerARExample : MonoBehaviour
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The should draw face points.
|
||||
/// </summary>
|
||||
public bool isShowingFacePoints;
|
||||
|
||||
/// <summary>
|
||||
/// The is showing face points toggle.
|
||||
/// </summary>
|
||||
public Toggle isShowingFacePointsToggle;
|
||||
|
||||
/// <summary>
|
||||
/// The should draw axes.
|
||||
/// </summary>
|
||||
public bool isShowingAxes;
|
||||
|
||||
/// <summary>
|
||||
/// The is showing axes toggle.
|
||||
/// </summary>
|
||||
public Toggle isShowingAxesToggle;
|
||||
|
||||
/// <summary>
|
||||
/// The should draw head.
|
||||
/// </summary>
|
||||
public bool isShowingHead;
|
||||
|
||||
/// <summary>
|
||||
/// The is showing head toggle.
|
||||
/// </summary>
|
||||
public Toggle isShowingHeadToggle;
|
||||
|
||||
/// <summary>
|
||||
/// The should draw effects.
|
||||
/// </summary>
|
||||
public bool isShowingEffects;
|
||||
|
||||
/// <summary>
|
||||
/// The is showing effects toggle.
|
||||
/// </summary>
|
||||
public Toggle isShowingEffectsToggle;
|
||||
|
||||
/// <summary>
|
||||
/// The auto reset mode. if ture, Only if face is detected in each frame, face is tracked.
|
||||
/// </summary>
|
||||
public bool isAutoResetMode;
|
||||
|
||||
/// <summary>
|
||||
/// The auto reset mode toggle.
|
||||
/// </summary>
|
||||
public Toggle isAutoResetModeToggle;
|
||||
|
||||
/// <summary>
|
||||
/// The axes.
|
||||
/// </summary>
|
||||
public GameObject axes;
|
||||
|
||||
/// <summary>
|
||||
/// The head.
|
||||
/// </summary>
|
||||
public GameObject head;
|
||||
|
||||
/// <summary>
|
||||
/// The right eye.
|
||||
/// </summary>
|
||||
public GameObject rightEye;
|
||||
|
||||
/// <summary>
|
||||
/// The left eye.
|
||||
/// </summary>
|
||||
public GameObject leftEye;
|
||||
|
||||
/// <summary>
|
||||
/// The mouth.
|
||||
/// </summary>
|
||||
public GameObject mouth;
|
||||
|
||||
/// <summary>
|
||||
/// The rvec noise filter range.
|
||||
/// </summary>
|
||||
[Range(0, 50)]
|
||||
public float
|
||||
rvecNoiseFilterRange = 8;
|
||||
|
||||
/// <summary>
|
||||
/// The tvec noise filter range.
|
||||
/// </summary>
|
||||
[Range(0, 360)]
|
||||
public float
|
||||
tvecNoiseFilterRange = 90;
|
||||
|
||||
/// <summary>
|
||||
/// The gray mat.
|
||||
/// </summary>
|
||||
Mat grayMat;
|
||||
|
||||
/// <summary>
|
||||
/// The texture.
|
||||
/// </summary>
|
||||
Texture2D texture;
|
||||
|
||||
/// <summary>
|
||||
/// The cascade.
|
||||
/// </summary>
|
||||
CascadeClassifier cascade;
|
||||
|
||||
/// <summary>
|
||||
/// The face tracker.
|
||||
/// </summary>
|
||||
FaceTracker faceTracker;
|
||||
|
||||
/// <summary>
|
||||
/// The face tracker parameters.
|
||||
/// </summary>
|
||||
FaceTrackerParams faceTrackerParams;
|
||||
|
||||
/// <summary>
|
||||
/// The AR camera.
|
||||
/// </summary>
|
||||
public Camera ARCamera;
|
||||
|
||||
/// <summary>
|
||||
/// The cam matrix.
|
||||
/// </summary>
|
||||
Mat camMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// The dist coeffs.
|
||||
/// </summary>
|
||||
MatOfDouble distCoeffs;
|
||||
|
||||
/// <summary>
|
||||
/// The invert Y.
|
||||
/// </summary>
|
||||
Matrix4x4 invertYM;
|
||||
|
||||
/// <summary>
|
||||
/// The transformation m.
|
||||
/// </summary>
|
||||
Matrix4x4 transformationM = new Matrix4x4();
|
||||
|
||||
/// <summary>
|
||||
/// The invert Z.
|
||||
/// </summary>
|
||||
Matrix4x4 invertZM;
|
||||
|
||||
/// <summary>
|
||||
/// The ar m.
|
||||
/// </summary>
|
||||
Matrix4x4 ARM;
|
||||
|
||||
/// <summary>
|
||||
/// The ar game object.
|
||||
/// </summary>
|
||||
public GameObject ARGameObject;
|
||||
|
||||
/// <summary>
|
||||
/// The should move AR camera.
|
||||
/// </summary>
|
||||
public bool shouldMoveARCamera;
|
||||
|
||||
/// <summary>
|
||||
/// The 3d face object points.
|
||||
/// </summary>
|
||||
MatOfPoint3f objectPoints;
|
||||
|
||||
/// <summary>
|
||||
/// The image points.
|
||||
/// </summary>
|
||||
MatOfPoint2f imagePoints;
|
||||
|
||||
/// <summary>
|
||||
/// The rvec.
|
||||
/// </summary>
|
||||
Mat rvec;
|
||||
|
||||
/// <summary>
|
||||
/// The tvec.
|
||||
/// </summary>
|
||||
Mat tvec;
|
||||
|
||||
/// <summary>
|
||||
/// The rot m.
|
||||
/// </summary>
|
||||
Mat rotM;
|
||||
|
||||
/// <summary>
|
||||
/// The old rvec.
|
||||
/// </summary>
|
||||
Mat oldRvec;
|
||||
|
||||
/// <summary>
|
||||
/// The old tvec.
|
||||
/// </summary>
|
||||
Mat oldTvec;
|
||||
|
||||
/// <summary>
|
||||
/// The web cam texture to mat helper.
|
||||
/// </summary>
|
||||
WebCamTextureToMatHelper webCamTextureToMatHelper;
|
||||
|
||||
/// <summary>
|
||||
/// The tracker_model_json_filepath.
|
||||
/// </summary>
|
||||
private string tracker_model_json_filepath;
|
||||
|
||||
/// <summary>
|
||||
/// The haarcascade_frontalface_alt_xml_filepath.
|
||||
/// </summary>
|
||||
private string haarcascade_frontalface_alt_xml_filepath;
|
||||
|
||||
|
||||
// Use this for initialization
|
||||
void Start()
|
||||
{
|
||||
isShowingFacePointsToggle.isOn = isShowingFacePoints;
|
||||
isShowingAxesToggle.isOn = isShowingAxes;
|
||||
isShowingHeadToggle.isOn = isShowingHead;
|
||||
isShowingEffectsToggle.isOn = isShowingEffects;
|
||||
isAutoResetModeToggle.isOn = isAutoResetMode;
|
||||
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
StartCoroutine(getFilePathCoroutine());
|
||||
#else
|
||||
tracker_model_json_filepath = Utils.getFilePath("tracker_model.json");
|
||||
haarcascade_frontalface_alt_xml_filepath = Utils.getFilePath("haarcascade_frontalface_alt.xml");
|
||||
Run();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
private IEnumerator getFilePathCoroutine()
|
||||
{
|
||||
var getFilePathAsync_0_Coroutine = StartCoroutine(Utils.getFilePathAsync("tracker_model.json", (result) => {
|
||||
tracker_model_json_filepath = result;
|
||||
}));
|
||||
var getFilePathAsync_1_Coroutine = StartCoroutine(Utils.getFilePathAsync("haarcascade_frontalface_alt.xml", (result) => {
|
||||
haarcascade_frontalface_alt_xml_filepath = result;
|
||||
}));
|
||||
|
||||
|
||||
yield return getFilePathAsync_0_Coroutine;
|
||||
yield return getFilePathAsync_1_Coroutine;
|
||||
|
||||
Run();
|
||||
}
|
||||
#endif
|
||||
|
||||
private void Run()
|
||||
{
|
||||
//set 3d face object points.
|
||||
objectPoints = new MatOfPoint3f(new Point3(-31, 72, 86),//l eye
|
||||
new Point3(31, 72, 86),//r eye
|
||||
new Point3(0, 40, 114),//nose
|
||||
new Point3(-20, 15, 90),//l mouse
|
||||
new Point3(20, 15, 90)//r mouse
|
||||
// ,
|
||||
// new Point3 (-70, 60, -9),//l ear
|
||||
// new Point3 (70, 60, -9)//r ear
|
||||
);
|
||||
imagePoints = new MatOfPoint2f();
|
||||
rvec = new Mat();
|
||||
tvec = new Mat();
|
||||
rotM = new Mat(3, 3, CvType.CV_64FC1);
|
||||
|
||||
//initialize FaceTracker
|
||||
faceTracker = new FaceTracker(tracker_model_json_filepath);
|
||||
//initialize FaceTrackerParams
|
||||
faceTrackerParams = new FaceTrackerParams();
|
||||
|
||||
cascade = new CascadeClassifier();
|
||||
cascade.load(haarcascade_frontalface_alt_xml_filepath);
|
||||
if (cascade.empty())
|
||||
{
|
||||
Debug.LogError("cascade file is not loaded.Please copy from “FaceTrackerExample/StreamingAssets/” to “Assets/StreamingAssets/” folder. ");
|
||||
}
|
||||
|
||||
|
||||
|
||||
webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper>();
|
||||
webCamTextureToMatHelper.Init();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the web cam texture to mat helper inited event.
|
||||
/// </summary>
|
||||
public void OnWebCamTextureToMatHelperInited()
|
||||
{
|
||||
Debug.Log("OnWebCamTextureToMatHelperInited");
|
||||
|
||||
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);
|
||||
|
||||
Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
|
||||
|
||||
float width = webCamTextureMat.width();
|
||||
float height = webCamTextureMat.height();
|
||||
|
||||
float imageSizeScale = 1.0f;
|
||||
|
||||
width = gameObject.transform.localScale.x;
|
||||
height = gameObject.transform.localScale.y;
|
||||
|
||||
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;
|
||||
imageSizeScale = (float)Screen.height / (float)Screen.width;
|
||||
} else
|
||||
{
|
||||
Camera.main.orthographicSize = height / 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int max_d = (int)Mathf.Max(width, height);
|
||||
double fx = max_d;
|
||||
double fy = max_d;
|
||||
double cx = width / 2.0f;
|
||||
double cy = height / 2.0f;
|
||||
camMatrix = new Mat(3, 3, CvType.CV_64FC1);
|
||||
camMatrix.put(0, 0, fx);
|
||||
camMatrix.put(0, 1, 0);
|
||||
camMatrix.put(0, 2, cx);
|
||||
camMatrix.put(1, 0, 0);
|
||||
camMatrix.put(1, 1, fy);
|
||||
camMatrix.put(1, 2, cy);
|
||||
camMatrix.put(2, 0, 0);
|
||||
camMatrix.put(2, 1, 0);
|
||||
camMatrix.put(2, 2, 1.0f);
|
||||
Debug.Log("camMatrix " + camMatrix.dump());
|
||||
|
||||
distCoeffs = new MatOfDouble(0, 0, 0, 0);
|
||||
Debug.Log("distCoeffs " + distCoeffs.dump());
|
||||
|
||||
Size imageSize = new Size(width * imageSizeScale, height * imageSizeScale);
|
||||
double apertureWidth = 0;
|
||||
double apertureHeight = 0;
|
||||
double[] fovx = new double[1];
|
||||
double[] fovy = new double[1];
|
||||
double[] focalLength = new double[1];
|
||||
Point principalPoint = new Point(0, 0);
|
||||
double[] aspectratio = new double[1];
|
||||
|
||||
|
||||
Calib3d.calibrationMatrixValues(camMatrix, imageSize, apertureWidth, apertureHeight, fovx, fovy, focalLength, principalPoint, aspectratio);
|
||||
|
||||
Debug.Log("imageSize " + imageSize.ToString());
|
||||
Debug.Log("apertureWidth " + apertureWidth);
|
||||
Debug.Log("apertureHeight " + apertureHeight);
|
||||
Debug.Log("fovx " + fovx [0]);
|
||||
Debug.Log("fovy " + fovy [0]);
|
||||
Debug.Log("focalLength " + focalLength [0]);
|
||||
Debug.Log("principalPoint " + principalPoint.ToString());
|
||||
Debug.Log("aspectratio " + aspectratio [0]);
|
||||
|
||||
|
||||
//To convert the difference of the FOV value of the OpenCV and Unity.
|
||||
double fovXScale = (2.0 * Mathf.Atan((float)(imageSize.width / (2.0 * fx)))) / (Mathf.Atan2((float)cx, (float)fx) + Mathf.Atan2((float)(imageSize.width - cx), (float)fx));
|
||||
double fovYScale = (2.0 * Mathf.Atan((float)(imageSize.height / (2.0 * fy)))) / (Mathf.Atan2((float)cy, (float)fy) + Mathf.Atan2((float)(imageSize.height - cy), (float)fy));
|
||||
|
||||
Debug.Log("fovXScale " + fovXScale);
|
||||
Debug.Log("fovYScale " + fovYScale);
|
||||
|
||||
|
||||
//Adjust Unity Camera FOV https://github.com/opencv/opencv/commit/8ed1945ccd52501f5ab22bdec6aa1f91f1e2cfd4
|
||||
if (widthScale < heightScale)
|
||||
{
|
||||
ARCamera.fieldOfView = (float)(fovx [0] * fovXScale);
|
||||
} else
|
||||
{
|
||||
ARCamera.fieldOfView = (float)(fovy [0] * fovYScale);
|
||||
}
|
||||
|
||||
|
||||
|
||||
invertYM = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1, -1, 1));
|
||||
Debug.Log("invertYM " + invertYM.ToString());
|
||||
|
||||
invertZM = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1, 1, -1));
|
||||
Debug.Log("invertZM " + invertZM.ToString());
|
||||
|
||||
|
||||
|
||||
grayMat = new Mat(webCamTextureMat.rows(), webCamTextureMat.cols(), CvType.CV_8UC1);
|
||||
|
||||
|
||||
|
||||
|
||||
axes.SetActive(false);
|
||||
head.SetActive(false);
|
||||
rightEye.SetActive(false);
|
||||
leftEye.SetActive(false);
|
||||
mouth.SetActive(false);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the web cam texture to mat helper disposed event.
|
||||
/// </summary>
|
||||
public void OnWebCamTextureToMatHelperDisposed()
|
||||
{
|
||||
Debug.Log("OnWebCamTextureToMatHelperDisposed");
|
||||
|
||||
faceTracker.reset();
|
||||
|
||||
grayMat.Dispose();
|
||||
camMatrix.Dispose();
|
||||
distCoeffs.Dispose();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
if (webCamTextureToMatHelper.IsPlaying() && webCamTextureToMatHelper.DidUpdateThisFrame())
|
||||
{
|
||||
|
||||
Mat rgbaMat = webCamTextureToMatHelper.GetMat();
|
||||
|
||||
|
||||
//convert image to greyscale
|
||||
Imgproc.cvtColor(rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
|
||||
|
||||
|
||||
if (isAutoResetMode || faceTracker.getPoints().Count <= 0)
|
||||
{
|
||||
// Debug.Log ("detectFace");
|
||||
|
||||
//convert image to greyscale
|
||||
using (Mat equalizeHistMat = new Mat ())
|
||||
using (MatOfRect faces = new MatOfRect ())
|
||||
{
|
||||
|
||||
Imgproc.equalizeHist(grayMat, equalizeHistMat);
|
||||
|
||||
cascade.detectMultiScale(equalizeHistMat, faces, 1.1f, 2, 0
|
||||
| Objdetect.CASCADE_FIND_BIGGEST_OBJECT
|
||||
| Objdetect.CASCADE_SCALE_IMAGE, new OpenCVForUnity.Size(equalizeHistMat.cols() * 0.15, equalizeHistMat.cols() * 0.15), new Size());
|
||||
|
||||
|
||||
|
||||
if (faces.rows() > 0)
|
||||
{
|
||||
// Debug.Log ("faces " + faces.dump ());
|
||||
|
||||
List<OpenCVForUnity.Rect> rectsList = faces.toList();
|
||||
List<Point[]> pointsList = faceTracker.getPoints();
|
||||
|
||||
if (isAutoResetMode)
|
||||
{
|
||||
//add initial face points from MatOfRect
|
||||
if (pointsList.Count <= 0)
|
||||
{
|
||||
faceTracker.addPoints(faces);
|
||||
// Debug.Log ("reset faces ");
|
||||
} else
|
||||
{
|
||||
|
||||
for (int i = 0; i < rectsList.Count; i++)
|
||||
{
|
||||
|
||||
OpenCVForUnity.Rect trackRect = new OpenCVForUnity.Rect(rectsList [i].x + rectsList [i].width / 3, rectsList [i].y + rectsList [i].height / 2, rectsList [i].width / 3, rectsList [i].height / 3);
|
||||
//It determines whether nose point has been included in trackRect.
|
||||
if (i < pointsList.Count && !trackRect.contains(pointsList [i] [67]))
|
||||
{
|
||||
rectsList.RemoveAt(i);
|
||||
pointsList.RemoveAt(i);
|
||||
// Debug.Log ("remove " + i);
|
||||
}
|
||||
Imgproc.rectangle(rgbaMat, new Point(trackRect.x, trackRect.y), new Point(trackRect.x + trackRect.width, trackRect.y + trackRect.height), new Scalar(0, 0, 255, 255), 2);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
faceTracker.addPoints(faces);
|
||||
}
|
||||
|
||||
//draw face rect
|
||||
for (int i = 0; i < rectsList.Count; i++)
|
||||
{
|
||||
#if OPENCV_2
|
||||
Core.rectangle (rgbaMat, new Point (rectsLIst [i].x, rectsList [i].y), new Point (rectsList [i].x + rectsList [i].width, rectsList [i].y + rectsList [i].height), new Scalar (255, 0, 0, 255), 2);
|
||||
#else
|
||||
Imgproc.rectangle(rgbaMat, new Point(rectsList [i].x, rectsList [i].y), new Point(rectsList [i].x + rectsList [i].width, rectsList [i].y + rectsList [i].height), new Scalar(255, 0, 0, 255), 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
if (isAutoResetMode)
|
||||
{
|
||||
faceTracker.reset();
|
||||
|
||||
rightEye.SetActive(false);
|
||||
leftEye.SetActive(false);
|
||||
head.SetActive(false);
|
||||
mouth.SetActive(false);
|
||||
axes.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//track face points.if face points <= 0, always return false.
|
||||
if (faceTracker.track(grayMat, faceTrackerParams))
|
||||
{
|
||||
if (isShowingFacePoints)
|
||||
faceTracker.draw(rgbaMat, new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255));
|
||||
|
||||
#if OPENCV_2
|
||||
Core.putText (rgbaMat, "'Tap' or 'Space Key' to Reset", new Point (5, rgbaMat.rows () - 5), Core.FONT_HERSHEY_SIMPLEX, 0.8, new Scalar (255, 255, 255, 255), 2, Core.LINE_AA, false);
|
||||
#else
|
||||
Imgproc.putText(rgbaMat, "'Tap' or 'Space Key' to Reset", new Point(5, rgbaMat.rows() - 5), Core.FONT_HERSHEY_SIMPLEX, 0.8, new Scalar(255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
|
||||
#endif
|
||||
|
||||
|
||||
Point[] points = faceTracker.getPoints() [0];
|
||||
|
||||
|
||||
if (points.Length > 0)
|
||||
{
|
||||
|
||||
// for (int i = 0; i < points.Length; i++) {
|
||||
// #if OPENCV_2
|
||||
// Core.putText (rgbaMat, "" + i, new Point (points [i].x, points [i].y), Core.FONT_HERSHEY_SIMPLEX, 0.3, new Scalar (0, 0, 255, 255), 2, Core.LINE_AA, false);
|
||||
// #else
|
||||
// Imgproc.putText (rgbaMat, "" + i, new Point (points [i].x, points [i].y), Core.FONT_HERSHEY_SIMPLEX, 0.3, new Scalar (0, 0, 255, 255), 2, Core.LINE_AA, false);
|
||||
// #endif
|
||||
// }
|
||||
|
||||
|
||||
imagePoints.fromArray(
|
||||
points [31],//l eye
|
||||
points [36],//r eye
|
||||
points [67],//nose
|
||||
points [48],//l mouth
|
||||
points [54] //r mouth
|
||||
// ,
|
||||
// points [0],//l ear
|
||||
// points [14]//r ear
|
||||
);
|
||||
|
||||
|
||||
Calib3d.solvePnP(objectPoints, imagePoints, camMatrix, distCoeffs, rvec, tvec);
|
||||
|
||||
bool isRefresh = false;
|
||||
|
||||
if (tvec.get(2, 0) [0] > 0 && tvec.get(2, 0) [0] < 1200 * ((float)rgbaMat.cols() / (float)webCamTextureToMatHelper.requestWidth))
|
||||
{
|
||||
|
||||
isRefresh = true;
|
||||
|
||||
if (oldRvec == null)
|
||||
{
|
||||
oldRvec = new Mat();
|
||||
rvec.copyTo(oldRvec);
|
||||
}
|
||||
if (oldTvec == null)
|
||||
{
|
||||
oldTvec = new Mat();
|
||||
tvec.copyTo(oldTvec);
|
||||
}
|
||||
|
||||
|
||||
//filter Rvec Noise.
|
||||
using (Mat absDiffRvec = new Mat ())
|
||||
{
|
||||
Core.absdiff(rvec, oldRvec, absDiffRvec);
|
||||
|
||||
// Debug.Log ("absDiffRvec " + absDiffRvec.dump());
|
||||
|
||||
using (Mat cmpRvec = new Mat ())
|
||||
{
|
||||
Core.compare(absDiffRvec, new Scalar(rvecNoiseFilterRange), cmpRvec, Core.CMP_GT);
|
||||
|
||||
if (Core.countNonZero(cmpRvec) > 0)
|
||||
isRefresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//filter Tvec Noise.
|
||||
using (Mat absDiffTvec = new Mat ())
|
||||
{
|
||||
Core.absdiff(tvec, oldTvec, absDiffTvec);
|
||||
|
||||
// Debug.Log ("absDiffRvec " + absDiffRvec.dump());
|
||||
|
||||
using (Mat cmpTvec = new Mat ())
|
||||
{
|
||||
Core.compare(absDiffTvec, new Scalar(tvecNoiseFilterRange), cmpTvec, Core.CMP_GT);
|
||||
|
||||
if (Core.countNonZero(cmpTvec) > 0)
|
||||
isRefresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (isRefresh)
|
||||
{
|
||||
|
||||
if (isShowingEffects)
|
||||
rightEye.SetActive(true);
|
||||
if (isShowingEffects)
|
||||
leftEye.SetActive(true);
|
||||
if (isShowingHead)
|
||||
head.SetActive(true);
|
||||
if (isShowingAxes)
|
||||
axes.SetActive(true);
|
||||
|
||||
|
||||
if ((Mathf.Abs((float)(points [48].x - points [56].x)) < Mathf.Abs((float)(points [31].x - points [36].x)) / 2.2
|
||||
&& Mathf.Abs((float)(points [51].y - points [57].y)) > Mathf.Abs((float)(points [31].x - points [36].x)) / 2.9)
|
||||
|| Mathf.Abs((float)(points [51].y - points [57].y)) > Mathf.Abs((float)(points [31].x - points [36].x)) / 2.7)
|
||||
{
|
||||
|
||||
if (isShowingEffects)
|
||||
mouth.SetActive(true);
|
||||
|
||||
} else
|
||||
{
|
||||
if (isShowingEffects)
|
||||
mouth.SetActive(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
rvec.copyTo(oldRvec);
|
||||
tvec.copyTo(oldTvec);
|
||||
|
||||
Calib3d.Rodrigues(rvec, rotM);
|
||||
|
||||
transformationM .SetRow(0, new Vector4((float)rotM.get(0, 0) [0], (float)rotM.get(0, 1) [0], (float)rotM.get(0, 2) [0], (float)tvec.get(0, 0) [0]));
|
||||
transformationM.SetRow(1, new Vector4((float)rotM.get(1, 0) [0], (float)rotM.get(1, 1) [0], (float)rotM.get(1, 2) [0], (float)tvec.get(1, 0) [0]));
|
||||
transformationM.SetRow(2, new Vector4((float)rotM.get(2, 0) [0], (float)rotM.get(2, 1) [0], (float)rotM.get(2, 2) [0], (float)tvec.get(2, 0) [0]));
|
||||
transformationM.SetRow(3, new Vector4(0, 0, 0, 1));
|
||||
|
||||
if (shouldMoveARCamera)
|
||||
{
|
||||
|
||||
if (ARGameObject != null)
|
||||
{
|
||||
ARM = ARGameObject.transform.localToWorldMatrix * invertZM * transformationM.inverse * invertYM;
|
||||
ARUtils.SetTransformFromMatrix(ARCamera.transform, ref ARM);
|
||||
ARGameObject.SetActive(true);
|
||||
}
|
||||
} else
|
||||
{
|
||||
ARM = ARCamera.transform.localToWorldMatrix * invertYM * transformationM * invertZM;
|
||||
|
||||
if (ARGameObject != null)
|
||||
{
|
||||
ARUtils.SetTransformFromMatrix(ARGameObject.transform, ref ARM);
|
||||
ARGameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Core.putText (rgbaMat, "W:" + rgbaMat.width () + " H:" + rgbaMat.height () + " SO:" + Screen.orientation, new Point (5, rgbaMat.rows () - 10), Core.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar (255, 255, 255, 255), 2, Core.LINE_AA, false);
|
||||
|
||||
Utils.matToTexture2D(rgbaMat, texture, webCamTextureToMatHelper.GetBufferColors());
|
||||
|
||||
}
|
||||
|
||||
if (Input.GetKeyUp(KeyCode.Space) || Input.touchCount > 0)
|
||||
{
|
||||
faceTracker.reset();
|
||||
if (oldRvec != null)
|
||||
{
|
||||
oldRvec.Dispose();
|
||||
oldRvec = null;
|
||||
}
|
||||
if (oldTvec != null)
|
||||
{
|
||||
oldTvec.Dispose();
|
||||
oldTvec = null;
|
||||
}
|
||||
|
||||
rightEye.SetActive(false);
|
||||
leftEye.SetActive(false);
|
||||
head.SetActive(false);
|
||||
mouth.SetActive(false);
|
||||
axes.SetActive(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the disable event.
|
||||
/// </summary>
|
||||
void OnDisable()
|
||||
{
|
||||
webCamTextureToMatHelper.Dispose();
|
||||
|
||||
if (cascade != null)
|
||||
cascade.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the back button event.
|
||||
/// </summary>
|
||||
public void OnBackButton()
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
SceneManager.LoadScene ("FaceTrackerExample");
|
||||
#else
|
||||
Application.LoadLevel("FaceTrackerExample");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the play button event.
|
||||
/// </summary>
|
||||
public void OnPlayButton()
|
||||
{
|
||||
webCamTextureToMatHelper.Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the pause button event.
|
||||
/// </summary>
|
||||
public void OnPauseButton()
|
||||
{
|
||||
webCamTextureToMatHelper.Pause();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the stop button event.
|
||||
/// </summary>
|
||||
public void OnStopButton()
|
||||
{
|
||||
webCamTextureToMatHelper.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the change camera button event.
|
||||
/// </summary>
|
||||
public void OnChangeCameraButton()
|
||||
{
|
||||
webCamTextureToMatHelper.Init(null, webCamTextureToMatHelper.requestWidth, webCamTextureToMatHelper.requestHeight, !webCamTextureToMatHelper.requestIsFrontFacing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the is showing face points toggle event.
|
||||
/// </summary>
|
||||
public void OnIsShowingFacePointsToggle()
|
||||
{
|
||||
if (isShowingFacePointsToggle.isOn)
|
||||
{
|
||||
isShowingFacePoints = true;
|
||||
} else
|
||||
{
|
||||
isShowingFacePoints = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the is showing axes toggle event.
|
||||
/// </summary>
|
||||
public void OnIsShowingAxesToggle()
|
||||
{
|
||||
if (isShowingAxesToggle.isOn)
|
||||
{
|
||||
isShowingAxes = true;
|
||||
} else
|
||||
{
|
||||
isShowingAxes = false;
|
||||
axes.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the is showing head toggle event.
|
||||
/// </summary>
|
||||
public void OnIsShowingHeadToggle()
|
||||
{
|
||||
if (isShowingHeadToggle.isOn)
|
||||
{
|
||||
isShowingHead = true;
|
||||
} else
|
||||
{
|
||||
isShowingHead = false;
|
||||
head.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the is showin effects toggle event.
|
||||
/// </summary>
|
||||
public void OnIsShowingEffectsToggle()
|
||||
{
|
||||
if (isShowingEffectsToggle.isOn)
|
||||
{
|
||||
isShowingEffects = true;
|
||||
} else
|
||||
{
|
||||
isShowingEffects = false;
|
||||
rightEye.SetActive(false);
|
||||
leftEye.SetActive(false);
|
||||
mouth.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the change auto reset mode toggle event.
|
||||
/// </summary>
|
||||
public void OnIsAutoResetModeToggle()
|
||||
{
|
||||
if (isAutoResetModeToggle.isOn)
|
||||
{
|
||||
isAutoResetMode = true;
|
||||
} else
|
||||
{
|
||||
isAutoResetMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
using UnityEngine.SceneManagement;
|
||||
#endif
|
||||
|
||||
namespace FaceTrackerExample
|
||||
{
|
||||
/// <summary>
|
||||
/// Face tracker example.
|
||||
/// </summary>
|
||||
public class FaceTrackerExample : MonoBehaviour
|
||||
{
|
||||
|
||||
// Use this for initialization
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnShowLicenseButton()
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
SceneManager.LoadScene ("ShowLicense");
|
||||
#else
|
||||
Application.LoadLevel("ShowLicense");
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnTexture2DFaceTrackerExample()
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
SceneManager.LoadScene ("Texture2DFaceTrackerExample");
|
||||
#else
|
||||
Application.LoadLevel("Texture2DFaceTrackerExample");
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnWebCamTextureFaceTrackerExample()
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
SceneManager.LoadScene ("WebCamTextureFaceTrackerExample");
|
||||
#else
|
||||
Application.LoadLevel("WebCamTextureFaceTrackerExample");
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnFaceTrackerARExample()
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
SceneManager.LoadScene ("FaceTrackerARExample");
|
||||
#else
|
||||
Application.LoadLevel("FaceTrackerARExample");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
using UnityEngine.SceneManagement;
|
||||
#endif
|
||||
|
||||
namespace FaceTrackerExample
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Show license.
|
||||
/// </summary>
|
||||
public class ShowLicense : MonoBehaviour
|
||||
{
|
||||
|
||||
// Use this for initialization
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnBackButton()
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
SceneManager.LoadScene ("FaceTrackerExample");
|
||||
#else
|
||||
Application.LoadLevel("FaceTrackerExample");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
using UnityEngine.SceneManagement;
|
||||
#endif
|
||||
using OpenCVForUnity;
|
||||
using OpenCVFaceTracker;
|
||||
|
||||
namespace FaceTrackerExample
|
||||
{
|
||||
/// <summary>
|
||||
/// Texture2D face tracker example.
|
||||
/// </summary>
|
||||
public class Texture2DFaceTrackerExample : MonoBehaviour
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The image texture.
|
||||
/// </summary>
|
||||
public Texture2D imgTexture;
|
||||
|
||||
/// <summary>
|
||||
/// The tracker_model_json_filepath.
|
||||
/// </summary>
|
||||
private string tracker_model_json_filepath;
|
||||
|
||||
/// <summary>
|
||||
/// The haarcascade_frontalface_alt_xml_filepath.
|
||||
/// </summary>
|
||||
private string haarcascade_frontalface_alt_xml_filepath;
|
||||
|
||||
// Use this for initialization
|
||||
void Start()
|
||||
{
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
StartCoroutine(getFilePathCoroutine());
|
||||
#else
|
||||
tracker_model_json_filepath = Utils.getFilePath("tracker_model.json");
|
||||
haarcascade_frontalface_alt_xml_filepath = Utils.getFilePath("haarcascade_frontalface_alt.xml");
|
||||
Run();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
private IEnumerator getFilePathCoroutine()
|
||||
{
|
||||
var getFilePathAsync_0_Coroutine = StartCoroutine(Utils.getFilePathAsync("tracker_model.json", (result) => {
|
||||
tracker_model_json_filepath = result;
|
||||
}));
|
||||
var getFilePathAsync_1_Coroutine = StartCoroutine(Utils.getFilePathAsync("haarcascade_frontalface_alt.xml", (result) => {
|
||||
haarcascade_frontalface_alt_xml_filepath = result;
|
||||
}));
|
||||
|
||||
|
||||
yield return getFilePathAsync_0_Coroutine;
|
||||
yield return getFilePathAsync_1_Coroutine;
|
||||
|
||||
Run();
|
||||
}
|
||||
#endif
|
||||
|
||||
private void Run()
|
||||
{
|
||||
gameObject.transform.localScale = new Vector3(imgTexture.width, imgTexture.height, 1);
|
||||
Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
|
||||
|
||||
float width = 0;
|
||||
float height = 0;
|
||||
|
||||
width = gameObject.transform.localScale.x;
|
||||
height = gameObject.transform.localScale.y;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//initialize FaceTracker
|
||||
FaceTracker faceTracker = new FaceTracker(tracker_model_json_filepath);
|
||||
//initialize FaceTrackerParams
|
||||
FaceTrackerParams faceTrackerParams = new FaceTrackerParams();
|
||||
|
||||
|
||||
Mat imgMat = new Mat(imgTexture.height, imgTexture.width, CvType.CV_8UC4);
|
||||
|
||||
Utils.texture2DToMat(imgTexture, imgMat);
|
||||
Debug.Log("imgMat dst ToString " + imgMat.ToString());
|
||||
|
||||
|
||||
CascadeClassifier cascade = new CascadeClassifier();
|
||||
cascade.load(haarcascade_frontalface_alt_xml_filepath);
|
||||
if (cascade.empty())
|
||||
{
|
||||
Debug.LogError("cascade file is not loaded.Please copy from “FaceTrackerExample/StreamingAssets/” to “Assets/StreamingAssets/” folder. ");
|
||||
}
|
||||
|
||||
//convert image to greyscale
|
||||
Mat gray = new Mat();
|
||||
Imgproc.cvtColor(imgMat, gray, Imgproc.COLOR_RGBA2GRAY);
|
||||
|
||||
|
||||
MatOfRect faces = new MatOfRect();
|
||||
|
||||
Imgproc.equalizeHist(gray, gray);
|
||||
|
||||
cascade.detectMultiScale(gray, faces, 1.1f, 2, 0
|
||||
// | Objdetect.CASCADE_FIND_BIGGEST_OBJECT
|
||||
| Objdetect.CASCADE_SCALE_IMAGE, new OpenCVForUnity.Size(gray.cols() * 0.05, gray.cols() * 0.05), new Size());
|
||||
|
||||
Debug.Log("faces " + faces.dump());
|
||||
|
||||
if (faces.rows() > 0)
|
||||
{
|
||||
//add initial face points from MatOfRect
|
||||
faceTracker.addPoints(faces);
|
||||
}
|
||||
|
||||
|
||||
//track face points.if face points <= 0, always return false.
|
||||
if (faceTracker.track(imgMat, faceTrackerParams))
|
||||
faceTracker.draw(imgMat, new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255));
|
||||
|
||||
|
||||
|
||||
Texture2D texture = new Texture2D(imgMat.cols(), imgMat.rows(), TextureFormat.RGBA32, false);
|
||||
|
||||
Utils.matToTexture2D(imgMat, texture);
|
||||
|
||||
gameObject.GetComponent<Renderer>().material.mainTexture = texture;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnBackButton()
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
SceneManager.LoadScene ("FaceTrackerExample");
|
||||
#else
|
||||
Application.LoadLevel("FaceTrackerExample");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a6e8ede0a97c7a469cdfd38f9fca45d
|
||||
folderAsset: yes
|
||||
timeCreated: 1486748112
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,97 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace FaceTrackerExample
|
||||
{
|
||||
/// <summary>
|
||||
/// AR utils.
|
||||
/// </summary>
|
||||
public class ARUtils
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Extract translation from transform matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">Transform matrix. This parameter is passed by reference
|
||||
/// to improve performance; no changes will be made to it.</param>
|
||||
/// <returns>
|
||||
/// Translation offset.
|
||||
/// </returns>
|
||||
public static Vector3 ExtractTranslationFromMatrix(ref Matrix4x4 matrix)
|
||||
{
|
||||
Vector3 translate;
|
||||
translate.x = matrix.m03;
|
||||
translate.y = matrix.m13;
|
||||
translate.z = matrix.m23;
|
||||
return translate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract rotation quaternion from transform matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">Transform matrix. This parameter is passed by reference
|
||||
/// to improve performance; no changes will be made to it.</param>
|
||||
/// <returns>
|
||||
/// Quaternion representation of rotation transform.
|
||||
/// </returns>
|
||||
public static Quaternion ExtractRotationFromMatrix(ref Matrix4x4 matrix)
|
||||
{
|
||||
Vector3 forward;
|
||||
forward.x = matrix.m02;
|
||||
forward.y = matrix.m12;
|
||||
forward.z = matrix.m22;
|
||||
|
||||
Vector3 upwards;
|
||||
upwards.x = matrix.m01;
|
||||
upwards.y = matrix.m11;
|
||||
upwards.z = matrix.m21;
|
||||
|
||||
return Quaternion.LookRotation(forward, upwards);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract scale from transform matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">Transform matrix. This parameter is passed by reference
|
||||
/// to improve performance; no changes will be made to it.</param>
|
||||
/// <returns>
|
||||
/// Scale vector.
|
||||
/// </returns>
|
||||
public static Vector3 ExtractScaleFromMatrix(ref Matrix4x4 matrix)
|
||||
{
|
||||
Vector3 scale;
|
||||
scale.x = new Vector4(matrix.m00, matrix.m10, matrix.m20, matrix.m30).magnitude;
|
||||
scale.y = new Vector4(matrix.m01, matrix.m11, matrix.m21, matrix.m31).magnitude;
|
||||
scale.z = new Vector4(matrix.m02, matrix.m12, matrix.m22, matrix.m32).magnitude;
|
||||
return scale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract position, rotation and scale from TRS matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">Transform matrix. This parameter is passed by reference
|
||||
/// to improve performance; no changes will be made to it.</param>
|
||||
/// <param name="localPosition">Output position.</param>
|
||||
/// <param name="localRotation">Output rotation.</param>
|
||||
/// <param name="localScale">Output scale.</param>
|
||||
public static void DecomposeMatrix(ref Matrix4x4 matrix, out Vector3 localPosition, out Quaternion localRotation, out Vector3 localScale)
|
||||
{
|
||||
localPosition = ExtractTranslationFromMatrix(ref matrix);
|
||||
localRotation = ExtractRotationFromMatrix(ref matrix);
|
||||
localScale = ExtractScaleFromMatrix(ref matrix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set transform component from TRS matrix.
|
||||
/// </summary>
|
||||
/// <param name="transform">Transform component.</param>
|
||||
/// <param name="matrix">Transform matrix. This parameter is passed by reference
|
||||
/// to improve performance; no changes will be made to it.</param>
|
||||
public static void SetTransformFromMatrix(Transform transform, ref Matrix4x4 matrix)
|
||||
{
|
||||
transform.localPosition = ExtractTranslationFromMatrix(ref matrix);
|
||||
transform.localRotation = ExtractRotationFromMatrix(ref matrix);
|
||||
transform.localScale = ExtractScaleFromMatrix(ref matrix);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,510 @@
|
|||
using OpenCVForUnity;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace FaceTrackerExample
|
||||
{
|
||||
/// <summary>
|
||||
/// Web cam texture to mat helper.
|
||||
/// </summary>
|
||||
public class WebCamTextureToMatHelper : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the device.
|
||||
/// </summary>
|
||||
public string requestDeviceName = null;
|
||||
|
||||
/// <summary>
|
||||
/// The width.
|
||||
/// </summary>
|
||||
public int requestWidth = 640;
|
||||
|
||||
/// <summary>
|
||||
/// The height.
|
||||
/// </summary>
|
||||
public int requestHeight = 480;
|
||||
|
||||
/// <summary>
|
||||
/// Should use front facing.
|
||||
/// </summary>
|
||||
public bool requestIsFrontFacing = false;
|
||||
|
||||
/// <summary>
|
||||
/// The flip vertical.
|
||||
/// </summary>
|
||||
public bool flipVertical = false;
|
||||
|
||||
/// <summary>
|
||||
/// The flip horizontal.
|
||||
/// </summary>
|
||||
public bool flipHorizontal = false;
|
||||
|
||||
/// <summary>
|
||||
/// The timeout frame count.
|
||||
/// </summary>
|
||||
public int timeoutFrameCount = 300;
|
||||
|
||||
/// <summary>
|
||||
/// The on inited event.
|
||||
/// </summary>
|
||||
public UnityEvent OnInitedEvent;
|
||||
|
||||
/// <summary>
|
||||
/// The on disposed event.
|
||||
/// </summary>
|
||||
public UnityEvent OnDisposedEvent;
|
||||
|
||||
/// <summary>
|
||||
/// The on error occurred event.
|
||||
/// </summary>
|
||||
public ErrorUnityEvent OnErrorOccurredEvent;
|
||||
|
||||
/// <summary>
|
||||
/// The web cam texture.
|
||||
/// </summary>
|
||||
WebCamTexture webCamTexture;
|
||||
|
||||
/// <summary>
|
||||
/// The web cam device.
|
||||
/// </summary>
|
||||
WebCamDevice webCamDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The rgba mat.
|
||||
/// </summary>
|
||||
Mat rgbaMat;
|
||||
|
||||
/// <summary>
|
||||
/// The rotated rgba mat
|
||||
/// </summary>
|
||||
Mat rotatedRgbaMat;
|
||||
|
||||
/// <summary>
|
||||
/// The colors.
|
||||
/// </summary>
|
||||
Color32[] colors;
|
||||
|
||||
/// <summary>
|
||||
/// The init waiting.
|
||||
/// </summary>
|
||||
bool initWaiting = false;
|
||||
|
||||
/// <summary>
|
||||
/// The init done.
|
||||
/// </summary>
|
||||
bool initDone = false;
|
||||
|
||||
/// <summary>
|
||||
/// The screenOrientation.
|
||||
/// </summary>
|
||||
ScreenOrientation screenOrientation = ScreenOrientation.Unknown;
|
||||
|
||||
[System.Serializable]
|
||||
public enum ErrorCode :int
|
||||
{
|
||||
CAMERA_DEVICE_NOT_EXIST = 0,
|
||||
TIMEOUT = 1,
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ErrorUnityEvent : UnityEngine.Events.UnityEvent<ErrorCode>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update ()
|
||||
{
|
||||
if (initDone) {
|
||||
if (screenOrientation != Screen.orientation) {
|
||||
StartCoroutine (init ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Init this instance.
|
||||
/// </summary>
|
||||
public void Init ()
|
||||
{
|
||||
if (initWaiting)
|
||||
return;
|
||||
|
||||
if (OnInitedEvent == null)
|
||||
OnInitedEvent = new UnityEvent ();
|
||||
if (OnDisposedEvent == null)
|
||||
OnDisposedEvent = new UnityEvent ();
|
||||
if (OnErrorOccurredEvent == null)
|
||||
OnErrorOccurredEvent = new ErrorUnityEvent ();
|
||||
|
||||
StartCoroutine (init ());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Init this instance.
|
||||
/// </summary>
|
||||
/// <param name="deviceName">Device name.</param>
|
||||
/// <param name="requestWidth">Request width.</param>
|
||||
/// <param name="requestHeight">Request height.</param>
|
||||
/// <param name="requestIsFrontFacing">If set to <c>true</c> request is front facing.</param>
|
||||
/// <param name="OnInited">On inited.</param>
|
||||
public void Init (string deviceName, int requestWidth, int requestHeight, bool requestIsFrontFacing)
|
||||
{
|
||||
if (initWaiting)
|
||||
return;
|
||||
|
||||
this.requestDeviceName = deviceName;
|
||||
this.requestWidth = requestWidth;
|
||||
this.requestHeight = requestHeight;
|
||||
this.requestIsFrontFacing = requestIsFrontFacing;
|
||||
if (OnInitedEvent == null)
|
||||
OnInitedEvent = new UnityEvent ();
|
||||
if (OnDisposedEvent == null)
|
||||
OnDisposedEvent = new UnityEvent ();
|
||||
if (OnErrorOccurredEvent == null)
|
||||
OnErrorOccurredEvent = new ErrorUnityEvent ();
|
||||
|
||||
StartCoroutine (init ());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Init this instance by coroutine.
|
||||
/// </summary>
|
||||
private IEnumerator init ()
|
||||
{
|
||||
if (initDone)
|
||||
dispose ();
|
||||
|
||||
initWaiting = true;
|
||||
|
||||
if (!String.IsNullOrEmpty (requestDeviceName)) {
|
||||
//Debug.Log ("deviceName is "+requestDeviceName);
|
||||
webCamTexture = new WebCamTexture (requestDeviceName, requestWidth, requestHeight);
|
||||
} else {
|
||||
//Debug.Log ("deviceName is 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 == requestIsFrontFacing) {
|
||||
|
||||
//Debug.Log (cameraIndex + " name " + WebCamTexture.devices [cameraIndex].name + " isFrontFacing " + WebCamTexture.devices [cameraIndex].isFrontFacing);
|
||||
webCamDevice = WebCamTexture.devices [cameraIndex];
|
||||
webCamTexture = new WebCamTexture (webCamDevice.name, requestWidth, requestHeight);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (webCamTexture == null) {
|
||||
if (WebCamTexture.devices.Length > 0) {
|
||||
webCamDevice = WebCamTexture.devices [0];
|
||||
webCamTexture = new WebCamTexture (webCamDevice.name, requestWidth, requestHeight);
|
||||
} else {
|
||||
//Debug.Log("Camera device does not exist.");
|
||||
initWaiting = false;
|
||||
|
||||
if (OnErrorOccurredEvent != null)
|
||||
OnErrorOccurredEvent.Invoke (ErrorCode.CAMERA_DEVICE_NOT_EXIST);
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
//Debug.Log ("name " + webCamTexture.name + " width " + webCamTexture.width + " height " + webCamTexture.height + " fps " + webCamTexture.requestedFPS);
|
||||
|
||||
// Starts the camera
|
||||
webCamTexture.Play ();
|
||||
|
||||
int initCount = 0;
|
||||
bool isTimeout = false;
|
||||
|
||||
while (true) {
|
||||
if (initCount > 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 (initCount > timeoutFrameCount) {
|
||||
isTimeout = true;
|
||||
break;
|
||||
}else {
|
||||
initCount++;
|
||||
}
|
||||
webCamTexture.GetPixels32 ();
|
||||
yield return new WaitForEndOfFrame ();
|
||||
}
|
||||
if (isTimeout) break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Debug.Log ("name " + webCamTexture.name + " width " + webCamTexture.width + " height " + webCamTexture.height + " fps " + webCamTexture.requestedFPS);
|
||||
Debug.Log ("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];
|
||||
rgbaMat = new Mat (webCamTexture.height, webCamTexture.width, CvType.CV_8UC4);
|
||||
|
||||
//Debug.Log ("Screen.orientation " + Screen.orientation);
|
||||
screenOrientation = Screen.orientation;
|
||||
|
||||
#if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
|
||||
if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown) {
|
||||
rotatedRgbaMat = new Mat (webCamTexture.width, webCamTexture.height, CvType.CV_8UC4);
|
||||
}
|
||||
#endif
|
||||
|
||||
initWaiting = false;
|
||||
initDone = true;
|
||||
|
||||
if (OnInitedEvent != null)
|
||||
OnInitedEvent.Invoke ();
|
||||
|
||||
break;
|
||||
} else {
|
||||
initCount++;
|
||||
yield return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (isTimeout) {
|
||||
//Debug.Log("Init time out.");
|
||||
webCamTexture.Stop ();
|
||||
webCamTexture = null;
|
||||
initWaiting = false;
|
||||
|
||||
if (OnErrorOccurredEvent != null)
|
||||
OnErrorOccurredEvent.Invoke (ErrorCode.TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ises the inited.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if inited was ised, <c>false</c> otherwise.</returns>
|
||||
public bool IsInited ()
|
||||
{
|
||||
return initDone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play this instance.
|
||||
/// </summary>
|
||||
public void Play ()
|
||||
{
|
||||
if (initDone)
|
||||
webCamTexture.Play ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause this instance.
|
||||
/// </summary>
|
||||
public void Pause ()
|
||||
{
|
||||
if (initDone)
|
||||
webCamTexture.Pause ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop this instance.
|
||||
/// </summary>
|
||||
public void Stop ()
|
||||
{
|
||||
if (initDone)
|
||||
webCamTexture.Stop ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ises the playing.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if playing was ised, <c>false</c> otherwise.</returns>
|
||||
public bool IsPlaying ()
|
||||
{
|
||||
if (!initDone)
|
||||
return false;
|
||||
return webCamTexture.isPlaying;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the web cam texture.
|
||||
/// </summary>
|
||||
/// <returns>The web cam texture.</returns>
|
||||
public WebCamTexture GetWebCamTexture ()
|
||||
{
|
||||
return (initDone) ? webCamTexture : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the web cam device.
|
||||
/// </summary>
|
||||
/// <returns>The web cam device.</returns>
|
||||
public WebCamDevice GetWebCamDevice ()
|
||||
{
|
||||
return webCamDevice;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dids the update this frame.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if update this frame was dided, <c>false</c> otherwise.</returns>
|
||||
public bool DidUpdateThisFrame ()
|
||||
{
|
||||
if (!initDone)
|
||||
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.
|
||||
/// </summary>
|
||||
/// <returns>The mat.</returns>
|
||||
public Mat GetMat ()
|
||||
{
|
||||
if (!initDone || !webCamTexture.isPlaying) {
|
||||
if (rotatedRgbaMat != null) {
|
||||
return rotatedRgbaMat;
|
||||
} else {
|
||||
return rgbaMat;
|
||||
}
|
||||
}
|
||||
|
||||
Utils.webCamTextureToMat (webCamTexture, rgbaMat, colors);
|
||||
|
||||
if (rotatedRgbaMat != null) {
|
||||
|
||||
using (Mat transposeRgbaMat = rgbaMat.t ()) {
|
||||
Core.flip (transposeRgbaMat, rotatedRgbaMat, 1);
|
||||
}
|
||||
|
||||
flipMat (rotatedRgbaMat);
|
||||
|
||||
return rotatedRgbaMat;
|
||||
} else {
|
||||
|
||||
flipMat (rgbaMat);
|
||||
|
||||
return rgbaMat;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flips the mat.
|
||||
/// </summary>
|
||||
/// <param name="mat">Mat.</param>
|
||||
private void flipMat (Mat mat)
|
||||
{
|
||||
int flipCode = int.MinValue;
|
||||
|
||||
if (webCamDevice.isFrontFacing) {
|
||||
if (webCamTexture.videoRotationAngle == 0) {
|
||||
flipCode = 1;
|
||||
} else if (webCamTexture.videoRotationAngle == 90) {
|
||||
flipCode = 1;
|
||||
}
|
||||
if (webCamTexture.videoRotationAngle == 180) {
|
||||
flipCode = 0;
|
||||
} else if (webCamTexture.videoRotationAngle == 270) {
|
||||
flipCode = 0;
|
||||
}
|
||||
} 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 Color32[] GetBufferColors ()
|
||||
{
|
||||
return colors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To release the resources for the init method.
|
||||
/// </summary>
|
||||
private void dispose ()
|
||||
{
|
||||
initWaiting = false;
|
||||
initDone = false;
|
||||
|
||||
if (webCamTexture != null) {
|
||||
webCamTexture.Stop ();
|
||||
webCamTexture = null;
|
||||
}
|
||||
if (rgbaMat != null) {
|
||||
rgbaMat.Dispose ();
|
||||
rgbaMat = null;
|
||||
}
|
||||
if (rotatedRgbaMat != null) {
|
||||
rotatedRgbaMat.Dispose ();
|
||||
rotatedRgbaMat = null;
|
||||
}
|
||||
|
||||
if (OnDisposedEvent != null)
|
||||
OnDisposedEvent.Invoke ();
|
||||
}
|
||||
|
||||
/// <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 void Dispose ()
|
||||
{
|
||||
if (initDone)
|
||||
dispose ();
|
||||
|
||||
colors = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,358 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.UI;
|
||||
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
using UnityEngine.SceneManagement;
|
||||
#endif
|
||||
using OpenCVForUnity;
|
||||
using OpenCVFaceTracker;
|
||||
|
||||
namespace FaceTrackerExample
|
||||
{
|
||||
/// <summary>
|
||||
/// WebCamTexture face tracker example.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(WebCamTextureToMatHelper))]
|
||||
public class WebCamTextureFaceTrackerExample : MonoBehaviour
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The auto reset mode. if ture, Only if face is detected in each frame, face is tracked.
|
||||
/// </summary>
|
||||
public bool isAutoResetMode;
|
||||
|
||||
/// <summary>
|
||||
/// The auto reset mode toggle.
|
||||
/// </summary>
|
||||
public Toggle isAutoResetModeToggle;
|
||||
|
||||
/// <summary>
|
||||
/// The gray mat.
|
||||
/// </summary>
|
||||
Mat grayMat;
|
||||
|
||||
/// <summary>
|
||||
/// The texture.
|
||||
/// </summary>
|
||||
Texture2D texture;
|
||||
|
||||
/// <summary>
|
||||
/// The cascade.
|
||||
/// </summary>
|
||||
CascadeClassifier cascade;
|
||||
|
||||
/// <summary>
|
||||
/// The face tracker.
|
||||
/// </summary>
|
||||
FaceTracker faceTracker;
|
||||
|
||||
/// <summary>
|
||||
/// The face tracker parameters.
|
||||
/// </summary>
|
||||
FaceTrackerParams faceTrackerParams;
|
||||
|
||||
/// <summary>
|
||||
/// The web cam texture to mat helper.
|
||||
/// </summary>
|
||||
WebCamTextureToMatHelper webCamTextureToMatHelper;
|
||||
|
||||
/// <summary>
|
||||
/// The tracker_model_json_filepath.
|
||||
/// </summary>
|
||||
private string tracker_model_json_filepath;
|
||||
|
||||
/// <summary>
|
||||
/// The haarcascade_frontalface_alt_xml_filepath.
|
||||
/// </summary>
|
||||
private string haarcascade_frontalface_alt_xml_filepath;
|
||||
|
||||
|
||||
// Use this for initialization
|
||||
void Start()
|
||||
{
|
||||
isAutoResetModeToggle.isOn = isAutoResetMode;
|
||||
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
StartCoroutine(getFilePathCoroutine());
|
||||
#else
|
||||
tracker_model_json_filepath = Utils.getFilePath("tracker_model.json");
|
||||
haarcascade_frontalface_alt_xml_filepath = Utils.getFilePath("haarcascade_frontalface_alt.xml");
|
||||
Run();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
private IEnumerator getFilePathCoroutine()
|
||||
{
|
||||
var getFilePathAsync_0_Coroutine = StartCoroutine(Utils.getFilePathAsync("tracker_model.json", (result) => {
|
||||
tracker_model_json_filepath = result;
|
||||
}));
|
||||
var getFilePathAsync_1_Coroutine = StartCoroutine(Utils.getFilePathAsync("haarcascade_frontalface_alt.xml", (result) => {
|
||||
haarcascade_frontalface_alt_xml_filepath = result;
|
||||
}));
|
||||
|
||||
|
||||
yield return getFilePathAsync_0_Coroutine;
|
||||
yield return getFilePathAsync_1_Coroutine;
|
||||
|
||||
Run();
|
||||
}
|
||||
#endif
|
||||
|
||||
private void Run()
|
||||
{
|
||||
//initialize FaceTracker
|
||||
faceTracker = new FaceTracker(tracker_model_json_filepath);
|
||||
//initialize FaceTrackerParams
|
||||
faceTrackerParams = new FaceTrackerParams();
|
||||
|
||||
cascade = new CascadeClassifier();
|
||||
cascade.load(haarcascade_frontalface_alt_xml_filepath);
|
||||
if (cascade.empty())
|
||||
{
|
||||
Debug.LogError("cascade file is not loaded.Please copy from “FaceTrackerExample/StreamingAssets/” to “Assets/StreamingAssets/” folder. ");
|
||||
}
|
||||
|
||||
|
||||
webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper>();
|
||||
webCamTextureToMatHelper.Init();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the web cam texture to mat helper inited event.
|
||||
/// </summary>
|
||||
public void OnWebCamTextureToMatHelperInited()
|
||||
{
|
||||
Debug.Log("OnWebCamTextureToMatHelperInited");
|
||||
|
||||
Mat webCamTextureMat = webCamTextureToMatHelper.GetMat();
|
||||
|
||||
texture = new Texture2D(webCamTextureMat.cols(), webCamTextureMat.rows(), TextureFormat.RGBA32, false);
|
||||
|
||||
|
||||
gameObject.transform.localScale = new Vector3(webCamTextureMat.cols(), webCamTextureMat.rows(), 1);
|
||||
Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
|
||||
|
||||
float width = 0;
|
||||
float height = 0;
|
||||
|
||||
width = gameObject.transform.localScale.x;
|
||||
height = gameObject.transform.localScale.y;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
gameObject.GetComponent<Renderer>().material.mainTexture = texture;
|
||||
|
||||
|
||||
|
||||
grayMat = new Mat(webCamTextureMat.rows(), webCamTextureMat.cols(), CvType.CV_8UC1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the web cam texture to mat helper disposed event.
|
||||
/// </summary>
|
||||
public void OnWebCamTextureToMatHelperDisposed()
|
||||
{
|
||||
Debug.Log("OnWebCamTextureToMatHelperDisposed");
|
||||
|
||||
faceTracker.reset();
|
||||
grayMat.Dispose();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
if (webCamTextureToMatHelper.IsPlaying() && webCamTextureToMatHelper.DidUpdateThisFrame())
|
||||
{
|
||||
|
||||
Mat rgbaMat = webCamTextureToMatHelper.GetMat();
|
||||
|
||||
//convert image to greyscale
|
||||
Imgproc.cvtColor(rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
|
||||
|
||||
|
||||
if (isAutoResetMode || faceTracker.getPoints().Count <= 0)
|
||||
{
|
||||
// Debug.Log ("detectFace");
|
||||
|
||||
//convert image to greyscale
|
||||
using (Mat equalizeHistMat = new Mat ())
|
||||
using (MatOfRect faces = new MatOfRect ())
|
||||
{
|
||||
|
||||
Imgproc.equalizeHist(grayMat, equalizeHistMat);
|
||||
|
||||
cascade.detectMultiScale(equalizeHistMat, faces, 1.1f, 2, 0
|
||||
// | Objdetect.CASCADE_FIND_BIGGEST_OBJECT
|
||||
| Objdetect.CASCADE_SCALE_IMAGE, new OpenCVForUnity.Size(equalizeHistMat.cols() * 0.15, equalizeHistMat.cols() * 0.15), new Size());
|
||||
|
||||
if (faces.rows() > 0)
|
||||
{
|
||||
// Debug.Log ("faces " + faces.dump ());
|
||||
|
||||
List<OpenCVForUnity.Rect> rectsList = faces.toList();
|
||||
List<Point[]> pointsList = faceTracker.getPoints();
|
||||
|
||||
if (isAutoResetMode)
|
||||
{
|
||||
//add initial face points from MatOfRect
|
||||
if (pointsList.Count <= 0)
|
||||
{
|
||||
faceTracker.addPoints(faces);
|
||||
// Debug.Log ("reset faces ");
|
||||
} else
|
||||
{
|
||||
|
||||
for (int i = 0; i < rectsList.Count; i++)
|
||||
{
|
||||
|
||||
OpenCVForUnity.Rect trackRect = new OpenCVForUnity.Rect(rectsList [i].x + rectsList [i].width / 3, rectsList [i].y + rectsList [i].height / 2, rectsList [i].width / 3, rectsList [i].height / 3);
|
||||
//It determines whether nose point has been included in trackRect.
|
||||
if (i < pointsList.Count && !trackRect.contains(pointsList [i] [67]))
|
||||
{
|
||||
rectsList.RemoveAt(i);
|
||||
pointsList.RemoveAt(i);
|
||||
// Debug.Log ("remove " + i);
|
||||
}
|
||||
Imgproc.rectangle(rgbaMat, new Point(trackRect.x, trackRect.y), new Point(trackRect.x + trackRect.width, trackRect.y + trackRect.height), new Scalar(0, 0, 255, 255), 2);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
faceTracker.addPoints(faces);
|
||||
}
|
||||
//draw face rect
|
||||
for (int i = 0; i < rectsList.Count; i++)
|
||||
{
|
||||
#if OPENCV_2
|
||||
Core.rectangle (rgbaMat, new Point (rectsList [i].x, rectsList [i].y), new Point (rectsList [i].x + rectsLIst [i].width, rectsList [i].y + rectsList [i].height), new Scalar (255, 0, 0, 255), 2);
|
||||
#else
|
||||
Imgproc.rectangle(rgbaMat, new Point(rectsList [i].x, rectsList [i].y), new Point(rectsList [i].x + rectsList [i].width, rectsList [i].y + rectsList [i].height), new Scalar(255, 0, 0, 255), 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} else
|
||||
{
|
||||
if (isAutoResetMode)
|
||||
{
|
||||
faceTracker.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//track face points.if face points <= 0, always return false.
|
||||
if (faceTracker.track(grayMat, faceTrackerParams))
|
||||
faceTracker.draw(rgbaMat, new Scalar(255, 0, 0, 255), new Scalar(0, 255, 0, 255));
|
||||
|
||||
|
||||
#if OPENCV_2
|
||||
Core.putText (rgbaMat, "'Tap' or 'Space Key' to Reset", new Point (5, rgbaMat.rows () - 5), Core.FONT_HERSHEY_SIMPLEX, 0.8, new Scalar (255, 255, 255, 255), 2, Core.LINE_AA, false);
|
||||
#else
|
||||
Imgproc.putText(rgbaMat, "'Tap' or 'Space Key' to Reset", new Point(5, rgbaMat.rows() - 5), Core.FONT_HERSHEY_SIMPLEX, 0.8, new Scalar(255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
|
||||
#endif
|
||||
|
||||
|
||||
// Core.putText (rgbaMat, "W:" + rgbaMat.width () + " H:" + rgbaMat.height () + " SO:" + Screen.orientation, new Point (5, rgbaMat.rows () - 10), Core.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar (255, 255, 255, 255), 2, Core.LINE_AA, false);
|
||||
|
||||
Utils.matToTexture2D(rgbaMat, texture, webCamTextureToMatHelper.GetBufferColors());
|
||||
|
||||
}
|
||||
|
||||
if (Input.GetKeyUp(KeyCode.Space) || Input.touchCount > 0)
|
||||
{
|
||||
faceTracker.reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Raises the disable event.
|
||||
/// </summary>
|
||||
void OnDisable()
|
||||
{
|
||||
webCamTextureToMatHelper.Dispose();
|
||||
|
||||
if (cascade != null)
|
||||
cascade.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the back button event.
|
||||
/// </summary>
|
||||
public void OnBackButton()
|
||||
{
|
||||
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
|
||||
SceneManager.LoadScene ("FaceTrackerExample");
|
||||
#else
|
||||
Application.LoadLevel("FaceTrackerExample");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the play button event.
|
||||
/// </summary>
|
||||
public void OnPlayButton()
|
||||
{
|
||||
webCamTextureToMatHelper.Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the pause button event.
|
||||
/// </summary>
|
||||
public void OnPauseButton()
|
||||
{
|
||||
webCamTextureToMatHelper.Pause();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the stop button event.
|
||||
/// </summary>
|
||||
public void OnStopButton()
|
||||
{
|
||||
webCamTextureToMatHelper.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the change camera button event.
|
||||
/// </summary>
|
||||
public void OnChangeCameraButton()
|
||||
{
|
||||
webCamTextureToMatHelper.Init(null, webCamTextureToMatHelper.requestWidth, webCamTextureToMatHelper.requestHeight, !webCamTextureToMatHelper.requestIsFrontFacing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the change auto reset mode toggle event.
|
||||
/// </summary>
|
||||
public void OnIsAutoResetModeToggle()
|
||||
{
|
||||
if (isAutoResetModeToggle.isOn)
|
||||
{
|
||||
isAutoResetMode = true;
|
||||
} else
|
||||
{
|
||||
isAutoResetMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|