This commit is contained in:
EnoxSoftware 2017-01-16 08:07:57 +09:00
Коммит d72f21dbad
144 изменённых файлов: 50727 добавлений и 0 удалений

9
FaceMaskSample.meta Normal file
Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 0a4656c4fb866c742b5b03bc5b557c0c
folderAsset: yes
timeCreated: 1481919542
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6c14b2aabbafe6e48aa33810b4d3cd2e
folderAsset: yes
timeCreated: 1481920337
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,66 @@
Shader "Hide/FadeShader" {
Properties
{
_MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}
_Color ("Color", Color) = (1, 1, 1, 1)
_Fade ("Fade", Range(0,1)) = 0
}
SubShader
{
LOD 100
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType"="Plane"
}
Lighting Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float _Fade;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed4 base = tex2D(_MainTex, i.texcoord) * (_Color);
base.w = base.w * (1 - _Fade);
return base;
}
ENDCG
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 62d9b85face5173458f9fc79fcac7d20
timeCreated: 1482000749
licenseType: Free
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,175 @@
%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: mesh_material
m_Shader: {fileID: 4800000, guid: 62d9b85face5173458f9fc79fcac7d20, type: 3}
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}
data:
first:
name: _FadeTex
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _RuleTex
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
data:
first:
name: _Trans
second: 0
data:
first:
name: _Rule
second: 0
data:
first:
name: _Vague
second: .25
m_Colors:
data:
first:
name: _EmissionColor
second: {r: 0, g: 0, b: 0, a: 1}
data:
first:
name: _Color
second: {r: 1, g: 1, b: 1, a: 1}
data:
first:
name: _EmissionColorUI
second: {r: 1, g: 1, b: 1, a: 1}
data:
first:
name: _FadeColor
second: {r: 1, g: 1, b: 1, a: 1}

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1c7f2a21195b29a45a2605423d0ab4bb
timeCreated: 1481980266
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,25 @@
%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: 930bad9a49e0e4d4f953e03509cea6ad, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats: {}
m_Colors: {}

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 15698121b1adac346859c37d6b52726c
timeCreated: 1481920346
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 9fccf8951e3e8ef4c8df84b8e9b3a2af
folderAsset: yes
timeCreated: 1481980728
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,98 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &102270
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 4
m_Component:
- 4: {fileID: 418932}
- 33: {fileID: 3310974}
- 64: {fileID: 6496772}
- 23: {fileID: 2378456}
- 114: {fileID: 11487226}
m_Layer: 0
m_Name: TrackedMesh
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &418932
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 102270}
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: 0
--- !u!23 &2378456
MeshRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 102270}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_Materials:
- {fileID: 2100000, guid: 1c7f2a21195b29a45a2605423d0ab4bb, type: 2}
m_SubsetIndices:
m_StaticBatchRoot: {fileID: 0}
m_UseLightProbes: 1
m_ReflectionProbeUsage: 1
m_ProbeAnchor: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_ImportantGI: 0
m_AutoUVMaxDistance: .5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingOrder: 0
--- !u!33 &3310974
MeshFilter:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 102270}
m_Mesh: {fileID: 4300002, guid: b87e7b82bde36d14b8be320b8772fea7, type: 3}
--- !u!64 &6496772
MeshCollider:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 102270}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Convex: 0
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!114 &11487226
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 102270}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c47754ddde934e14c95f9de06ad6413d, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !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: 102270}
m_IsPrefabParent: 1

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6c2fbaa5846552f4a813a214779197dd
timeCreated: 1481982798
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
FaceMaskSample/ReadMe.pdf Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8a180bc8a88f50248bb53c8ccfd3c3a8
timeCreated: 1483809590
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: cac99c3cb04e63247a7417e6779861da
folderAsset: yes
timeCreated: 1481920777
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 419a4402b9c043942b41eb0d902bcf1a
folderAsset: yes
timeCreated: 1481920777
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,501 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace OpenCVForUnity.RectangleTrack
{
public class RectangleTracker : IDisposable
{
public List<TrackedObject> TrackedObjects
{
get { return trackedObjects; }
}
private List<TrackedObject> trackedObjects;
public TrackerParameters TrackerParameters
{
get { return trackerParameters; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
trackerParameters = value;
}
}
private TrackerParameters trackerParameters;
public List<float> weightsPositionsSmoothing
{
get { return _weightsPositionsSmoothing; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
_weightsPositionsSmoothing = value;
}
}
private List<float> _weightsPositionsSmoothing = new List<float>();
public List<float> weightsSizesSmoothing
{
get { return _weightsSizesSmoothing; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
_weightsSizesSmoothing = value;
}
}
private List<float> _weightsSizesSmoothing = new List<float>();
public RectangleTracker(TrackerParameters trackerParamerers = null)
{
trackedObjects = new List<TrackedObject>();
if (trackerParamerers != null)
{
this.trackerParameters = trackerParamerers;
}
else
{
this.trackerParameters = new TrackerParameters();
}
_weightsPositionsSmoothing.Add(1);
_weightsSizesSmoothing.Add(0.5f);
_weightsSizesSmoothing.Add(0.3f);
_weightsSizesSmoothing.Add(0.2f);
}
public enum TrackedRectState : int
{
NEW_RECTANGLE = -1,
INTERSECTED_RECTANGLE = -2
}
public void GetObjects(List<Rect> result, bool smoothing = true)
{
result.Clear();
int count = trackedObjects.Count;
for (int i = 0; i < count; i++)
{
Rect r;
if (smoothing)
{
r = getSmoothingRect(i);
}
else
{
r = trackedObjects[i].position;
}
if (trackedObjects[i].state > TrackedState.NEW_DISPLAYED && trackedObjects[i].state < TrackedState.NEW_HIDED)
result.Add(r);
//LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height);
//Debug.Log("GetObjects" + r.width + " " + r.height + " " + r.x + " " + r.y + " " + r.width + " " + r.height + " " + trackedObjects[i].state + " " + trackedObjects[i].numDetectedFrames + " " + trackedObjects[i].numFramesNotDetected);
}
}
public void GetObjects(List<TrackedRect> result, bool smoothing = true)
{
result.Clear();
int count = trackedObjects.Count;
for (int i = 0; i < count; i++)
{
Rect r;
if (smoothing)
{
r = getSmoothingRect(i);
}
else
{
r = trackedObjects[i].position;
}
result.Add(new TrackedRect(trackedObjects[i].id, r, trackedObjects[i].state, trackedObjects[i].numDetectedFrames, trackedObjects[i].numFramesNotDetected));
//LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height);
//Debug.Log("GetObjects" + r.width + " " + r.height + " " + r.x + " " + r.y + " " + r.width + " " + r.height + " " + trackedObjects[i].state + " " + trackedObjects[i].numDetectedFrames + " " + trackedObjects[i].numFramesNotDetected);
}
}
public void UpdateTrackedObjects(List<Rect> detectedObjects)
{
if (detectedObjects == null)
throw new ArgumentNullException("detectedObjects");
Rect[] correctionRects = CreateCorrectionBySpeedOfRects();
int N1 = (int)trackedObjects.Count;
int N2 = (int)detectedObjects.Count;
for (int i = 0; i < N1; i++)
{
trackedObjects[i].numDetectedFrames++;
}
int[] correspondence = Enumerable.Repeat<int>((int)TrackedRectState.NEW_RECTANGLE, N2).ToArray();
for (int i = 0; i < N1; i++)
{
TrackedObject curObject = trackedObjects[i];
int bestIndex = -1;
int bestArea = -1;
//int numpositions = (int)curObject.lastPositions.Count;
//if (numpositions > 0) UnityEngine.Debug.LogError("numpositions > 0 is false");
//Rect prevRect = curObject.lastPositions[numpositions - 1];
Rect prevRect = correctionRects[i];
for (int j = 0; j < N2; j++)
{
if (correspondence[j] >= 0)
{
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: j=" + j + " is rejected, because it has correspondence=" + correspondence[j]);
continue;
}
if (correspondence[j] != (int)TrackedRectState.NEW_RECTANGLE)
{
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: j=" + j + " is rejected, because it is intersected with another rectangle");
continue;
}
if (IsCollideByRectangle(prevRect, detectedObjects[j], trackerParameters.coeffRectangleOverlap))
{
Rect r = Intersect(prevRect, detectedObjects[j]);
if ((r.width > 0) && (r.height > 0))
{
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: There is intersection between prevRect and detectedRect r={" + r.x + ", " + r.y + ", " + r.width + ", " + r.height + "]");
correspondence[j] = (int)TrackedRectState.INTERSECTED_RECTANGLE;
if (r.area() > bestArea)
{
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: The area of intersection is " + r.area() + " it is better than bestArea= " + bestArea);
bestIndex = j;
bestArea = (int)r.area();
}
}
}
}
if (bestIndex >= 0)
{
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: The best correspondence for i=" + i + " is j=" + bestIndex);
correspondence[bestIndex] = i;
Rect bestRect = detectedObjects[bestIndex];
for (int j = 0; j < N2; j++)
{
if (correspondence[j] >= 0)
continue;
if (IsCollideByRectangle(detectedObjects[j], bestRect, trackerParameters.coeffRectangleOverlap))
{
Rect r = Intersect(detectedObjects[j], bestRect);
if ((r.width > 0) && (r.height > 0))
{
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: Found intersection between rectangles j= " + j + " and bestIndex= " + bestIndex + " rectangle j= " + j + " is marked as intersected");
correspondence[j] = (int)TrackedRectState.INTERSECTED_RECTANGLE;
}
}
}
}
else
{
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: There is no correspondence for i= " + i);
curObject.numFramesNotDetected++;
}
}
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: start second cycle");
for (int j = 0; j < N2; j++)
{
int i = correspondence[j];
if (i >= 0)
{//add position
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: add position");
trackedObjects[i].lastPositions.Add(detectedObjects[j]);
while ((int)trackedObjects[i].lastPositions.Count > (int)trackerParameters.numLastPositionsToTrack)
{
trackedObjects[i].lastPositions.Remove(trackedObjects[i].lastPositions[0]);
}
trackedObjects[i].numFramesNotDetected = 0;
if (trackedObjects[i].state != TrackedState.DELETED) trackedObjects[i].state = TrackedState.DISPLAYED;
}
else if (i == (int)TrackedRectState.NEW_RECTANGLE)
{ //new object
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: new object");
trackedObjects.Add(new TrackedObject(detectedObjects[j]));
}
else
{
//Debug.Log("DetectionBasedTracker::updateTrackedObjects: was auxiliary intersection");
}
}
int t = 0;
TrackedObject it;
while (t < trackedObjects.Count)
{
it = trackedObjects[t];
if (it.state == TrackedState.DELETED)
{
trackedObjects.Remove(it);
}
else if ((it.numFramesNotDetected > trackerParameters.maxTrackLifetime)//ALL
||
((it.numDetectedFrames <= trackerParameters.numStepsToWaitBeforeFirstShow)
&&
(it.numFramesNotDetected > trackerParameters.numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown))
)
{
it.state = TrackedState.DELETED;
t++;
}
else if (it.state >= TrackedState.DISPLAYED)//DISPLAYED, NEW_DISPLAYED, HIDED
{
if (it.numDetectedFrames < trackerParameters.numStepsToWaitBeforeFirstShow)
{
it.state = TrackedState.PENDING;
}
else if (it.numDetectedFrames == trackerParameters.numStepsToWaitBeforeFirstShow)
{
//i, trackedObjects[i].numDetectedFrames, innerParameters.numStepsToWaitBeforeFirstShow);
it.state = TrackedState.NEW_DISPLAYED;
}
else if (it.numFramesNotDetected == trackerParameters.numStepsToShowWithoutDetecting)
{
it.state = TrackedState.NEW_HIDED;
}
else if (it.numFramesNotDetected > trackerParameters.numStepsToShowWithoutDetecting)
{
it.state = TrackedState.HIDED;
}
t++;
}
else//NEW
{
t++;
}
}
}
public Rect[] CreateCorrectionBySpeedOfRects()
{
//Debug.Log("DetectionBasedTracker::process: get _rectsWhereRegions from previous positions");
Rect[] rectsWhereRegions = new Rect[trackedObjects.Count];
int count = trackedObjects.Count;
for (int i = 0; i < count; i++)
{
int n = trackedObjects[i].lastPositions.Count;
//if (n > 0) UnityEngine.Debug.LogError("n > 0 is false");
Rect r = trackedObjects[i].lastPositions[n - 1].clone();
/*
if (r.area() == 0)
{
Debug.Log("DetectionBasedTracker::process: ERROR: ATTENTION: strange algorithm's behavior: trackedObjects[i].rect() is empty");
continue;
}
*/
//correction by speed of rectangle
if (n > 1)
{
Point center = centerRect(r);
Point center_prev = centerRect(trackedObjects[i].lastPositions[n - 2]);
Point shift = new Point((center.x - center_prev.x) * trackerParameters.coeffObjectSpeedUsingInPrediction,
(center.y - center_prev.y) * trackerParameters.coeffObjectSpeedUsingInPrediction);
r.x += (int)Math.Round(shift.x);
r.y += (int)Math.Round(shift.y);
}
rectsWhereRegions[i] = r;
}
return rectsWhereRegions;
}
private Point centerRect(Rect r)
{
return new Point(r.x + (r.width / 2), r.y + (r.height / 2));
}
private Rect getSmoothingRect(int i)
{
//Debug.Log("trackedObjects[i].numFramesNotDetected: " + trackedObjects[i].numFramesNotDetected);
List<float> weightsSizesSmoothing = _weightsSizesSmoothing;
List<float> weightsPositionsSmoothing = _weightsPositionsSmoothing;
List<Rect> lastPositions = trackedObjects[i].lastPositions;
int N = lastPositions.Count;
if (N <= 0)
{
Debug.Log("DetectionBasedTracker::calcTrackedObjectPositionToShow: ERROR: no positions for i=" + i);
return new Rect();
}
int Nsize = Math.Min(N, (int)weightsSizesSmoothing.Count);
int Ncenter = Math.Min(N, (int)weightsPositionsSmoothing.Count);
Point center = new Point();
double w = 0, h = 0;
if (Nsize > 0)
{
double sum = 0;
for (int j = 0; j < Nsize; j++)
{
int k = N - j - 1;
w += lastPositions[k].width * weightsSizesSmoothing[j];
h += lastPositions[k].height * weightsSizesSmoothing[j];
sum += weightsSizesSmoothing[j];
}
w /= sum;
h /= sum;
}
else
{
w = lastPositions[N - 1].width;
h = lastPositions[N - 1].height;
}
if (Ncenter > 0)
{
double sum = 0;
for (int j = 0; j < Ncenter; j++)
{
int k = N - j - 1;
Point tl = lastPositions[k].tl();
Point br = lastPositions[k].br();
Point c1;
c1 = new Point(tl.x * 0.5f, tl.y * 0.5f);
Point c2;
c2 = new Point(br.x * 0.5f, br.y * 0.5f);
c1 = new Point(c1.x + c2.x, c1.y + c2.y);
center = new Point(center.x + (c1.x * weightsPositionsSmoothing[j]), center.y + (c1.y * weightsPositionsSmoothing[j]));
sum += weightsPositionsSmoothing[j];
}
center = new Point(center.x * (1 / sum), center.y * (1 / sum));
}
else
{
int k = N - 1;
Point tl = lastPositions[k].tl();
Point br = lastPositions[k].br();
Point c1;
c1 = new Point(tl.x * 0.5f, tl.y * 0.5f);
Point c2;
c2 = new Point(br.x * 0.5f, br.y * 0.5f);
center = new Point(c1.x + c2.x, c1.y + c2.y);
}
Point tl2 = new Point(center.x - (w * 0.5f), center.y - (h * 0.5f));
Rect res = new Rect((int)Math.Round(tl2.x), (int)Math.Round(tl2.y), (int)Math.Round(w), (int)Math.Round(h));
//Debug.Log("DetectionBasedTracker::calcTrackedObjectPositionToShow: Result for i=" + i + ": {" + res.x + ", " + res.y + ", " + res.width + ", " + res.height + "}");
return res;
}
public void Reset()
{
trackedObjects.Clear();
}
private Rect Intersect(Rect a, Rect b)
{
int x1 = Math.Max(a.x, b.x);
int x2 = Math.Min(a.x + a.width, b.x + b.width);
int y1 = Math.Max(a.y, b.y);
int y2 = Math.Min(a.y + a.height, b.y + b.height);
if (x2 >= x1 && y2 >= y1)
return new Rect(x1, y1, x2 - x1, y2 - y1);
else
return new Rect();
}
/*
private bool IsCollideByCircle(Rect a, Rect b, float coeffRectangleOverlap)
{
int r1 = (int)(a.width / 2.0f);
int r2 = (int)(b.width / 2.0f);
int px1 = a.x + r1;
int py1 = a.y + r1;
int px2 = b.x + r2;
int py2 = b.y + r2;
if ((px2 - px1) * (px2 - px1) + (py2 - py1) * (py2 - py1) <= (r1 + r2) * (r1 + r2) * coeffRectangleOverlap)
return true;
else
return false;
}
*/
private bool IsCollideByRectangle(Rect a, Rect b, float coeffRectangleOverlap)
{
int mw = (int)(a.width * coeffRectangleOverlap);
int mh = (int)(a.height * coeffRectangleOverlap);
int mx1 = (int)(a.x + (a.width - mw) / 2.0f);
int my1 = (int)(a.x + (a.height - mh) / 2.0f);
int mx2 = (int)(mx1 + mw);
int my2 = (int)(my1 + mh);
int ew = (int)(b.width * coeffRectangleOverlap);
int eh = (int)(b.height * coeffRectangleOverlap);
int ex1 = (int)(b.x + (b.width - ew) / 2.0f);
int ey1 = (int)(b.x + (b.height - eh) / 2.0f);
int ex2 = (int)(ex1 + ew);
int ey2 = (int)(ey1 + eh);
if (mx1 <= ex2 && ex1 <= mx2 && my1 <= ey2 && ey1 <= my2)
return true;
else
return false;
}
public void Dispose()
{
Reset();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 07e4b92dd6ea99d46b184b3c16346b74
timeCreated: 1481920777
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,53 @@
using PositionsVector = System.Collections.Generic.List<OpenCVForUnity.Rect>;
namespace OpenCVForUnity.RectangleTrack
{
public enum TrackedState : int
{
NEW = 0,
PENDING = 1,
NEW_DISPLAYED = 2,
DISPLAYED =3,
NEW_HIDED = 4,
HIDED = 5,
DELETED = 6
}
public class TrackedObject
{
public PositionsVector lastPositions;
public int numDetectedFrames;
public int numFramesNotDetected;
public int id;
public TrackedState state;
public OpenCVForUnity.Rect position
{
get { return lastPositions[lastPositions.Count - 1].clone(); }
}
static private int _id = 0;
public TrackedObject(OpenCVForUnity.Rect rect)
{
lastPositions = new PositionsVector();
numDetectedFrames = 1;
numFramesNotDetected = 0;
state = TrackedState.NEW;
lastPositions.Add(rect.clone());
_id = getNextId();
id = _id;
}
static int getNextId()
{
_id++;
return _id;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: be925ca4987066b44999e368e2998d73
timeCreated: 1481920777
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,19 @@
namespace OpenCVForUnity.RectangleTrack
{
public class TrackedRect : Rect
{
public int numDetectedFrames;
public int numFramesNotDetected;
public int id;
public TrackedState state;
public TrackedRect(int id, Rect rect, TrackedState state, int numDetectedFrames, int numFramesNotDetected)
: base(rect.x, rect.y, rect.width, rect.height)
{
this.numDetectedFrames = numDetectedFrames;
this.numFramesNotDetected = numFramesNotDetected;
this.id = id;
this.state = state;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ea62936eb7bff934396d4f5f77237fd2
timeCreated: 1481920777
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,33 @@
namespace OpenCVForUnity.RectangleTrack
{
public class TrackerParameters
{
public int numLastPositionsToTrack = 4;
public int numStepsToWaitBeforeFirstShow = 6;
public int numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown = 3;
public int numStepsToShowWithoutDetecting = 3;
public int maxTrackLifetime = 5;
public float coeffObjectSpeedUsingInPrediction = 0.8f;
public float coeffRectangleOverlap = 0.7f;
public TrackerParameters() {
}
public TrackerParameters Clone()
{
TrackerParameters trackerParameters = new TrackerParameters();
trackerParameters.numLastPositionsToTrack = numLastPositionsToTrack;
trackerParameters.numStepsToWaitBeforeFirstShow = numStepsToWaitBeforeFirstShow;
trackerParameters.numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown = numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown;
trackerParameters.numStepsToShowWithoutDetecting = numStepsToShowWithoutDetecting;
trackerParameters.maxTrackLifetime = maxTrackLifetime;
trackerParameters.coeffObjectSpeedUsingInPrediction = coeffObjectSpeedUsingInPrediction;
trackerParameters.coeffRectangleOverlap = coeffRectangleOverlap;
return trackerParameters;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d000e76268a8c4b4db04c3839c374ac1
timeCreated: 1481920777
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: d1e51e8d94b2e7949aefa30124982c6e
folderAsset: yes
timeCreated: 1481920749
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,313 @@
g DlibFaceLandmark68Mesh
v 81 4 0
v 79 -16 0
v 75 -37 0
v 70 -57 0
v 61 -76 0
v 49 -93 0
v 34 -105 0
v 18 -114 0
v -1 -115 0
v -20 -111 0
v -36 -99 0
v -49 -82 0
v -58 -62 0
v -63 -40 0
v -66 -19 0
v -66 3 0
v -63 25 0
v 74 15 0
v 68 27 0
v 54 29 0
v 41 27 0
v 26 22 0
v 6 25 0
v -7 34 0
v -23 41 0
v -39 42 0
v -50 32 0
v 15 11 0
v 14 -4 0
v 12 -18 0
v 11 -33 0
v 23 -43 0
v 16 -46 0
v 7 -48 0
v -1 -44 0
v -8 -39 0
v 58 7 0
v 51 13 0
v 40 14 0
v 32 7 0
v 40 3 0
v 51 3 0
v -7 12 0
v -15 21 0
v -26 24 0
v -35 19 0
v -28 13 0
v -17 11 0
v 30 -74 0
v 21 -69 0
v 13 -66 0
v 5 -66 0
v -1 -63 0
v -12 -63 0
v -22 -66 0
v -15 -74 0
v -5 -78 0
v 2 -80 0
v 10 -80 0
v 20 -79 0
v 25 -74 0
v 12 -71 0
v 5 -71 0
v -2 -69 0
v -18 -67 0
v -3 -70 0
v 4 -72 0
v 11 -73 0
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -0.9999999
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -0.9999999
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -0.9999999
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -0.9999999
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -0.9999999
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -0.9999999
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -0.9999999
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -0.9999999
vn 0 0 -0.9999999
vn 0 0 -1
vn 0 0 -0.9999999
vt 0.21875 0.5114943
vt 0.2256944 0.454023
vt 0.2395833 0.3936782
vt 0.2569444 0.3362069
vt 0.2881944 0.2816092
vt 0.3298611 0.2327586
vt 0.3819444 0.1982759
vt 0.4375 0.1724138
vt 0.5034722 0.1695402
vt 0.5694444 0.1810345
vt 0.625 0.2155172
vt 0.6701389 0.2643678
vt 0.7013889 0.3218391
vt 0.71875 0.3850575
vt 0.7291667 0.4454023
vt 0.7291667 0.5086207
vt 0.71875 0.5718391
vt 0.2430556 0.5431035
vt 0.2638889 0.5775862
vt 0.3125 0.5833333
vt 0.3576389 0.5775862
vt 0.4097222 0.5632184
vt 0.4791667 0.5718391
vt 0.5243056 0.5977011
vt 0.5798611 0.6178161
vt 0.6354167 0.6206896
vt 0.6736111 0.5919541
vt 0.4479167 0.5316092
vt 0.4513889 0.4885058
vt 0.4583333 0.4482759
vt 0.4618056 0.4051724
vt 0.4201389 0.3764368
vt 0.4444444 0.3678161
vt 0.4756944 0.362069
vt 0.5034722 0.3735632
vt 0.5277778 0.387931
vt 0.2986111 0.520115
vt 0.3229167 0.5373563
vt 0.3611111 0.5402299
vt 0.3888889 0.520115
vt 0.3611111 0.5086207
vt 0.3229167 0.5086207
vt 0.5243056 0.5344828
vt 0.5520833 0.5603448
vt 0.5902778 0.5689655
vt 0.6215278 0.5545977
vt 0.5972222 0.5373563
vt 0.5590278 0.5316092
vt 0.3958333 0.2873563
vt 0.4270833 0.3017241
vt 0.4548611 0.3103448
vt 0.4826389 0.3103448
vt 0.5034722 0.3189655
vt 0.5416667 0.3189655
vt 0.5763889 0.3103448
vt 0.5520833 0.2873563
vt 0.5173611 0.2758621
vt 0.4930556 0.2701149
vt 0.4652778 0.2701149
vt 0.4305556 0.2729885
vt 0.4131944 0.2873563
vt 0.4583333 0.295977
vt 0.4826389 0.295977
vt 0.5069444 0.3017241
vt 0.5625 0.3074713
vt 0.5104167 0.2988506
vt 0.4861111 0.2931035
vt 0.4618056 0.2902299
usemtl Hide/TransShader
usemap Hide/TransShader
f 1/1/1 2/2/2 37/37/37
f 2/2/2 42/42/42 37/37/37
f 2/2/2 32/32/32 42/42/42
f 42/42/42 32/32/32 41/41/41
f 41/41/41 32/32/32 30/30/30
f 41/41/41 30/30/30 40/40/40
f 40/40/40 30/30/30 29/29/29
f 40/40/40 29/29/29 28/28/28
f 40/40/40 28/28/28 22/22/22
f 39/39/39 40/40/40 22/22/22
f 21/21/21 39/39/39 22/22/22
f 38/38/38 39/39/39 21/21/21
f 38/38/38 21/21/21 20/20/20
f 19/19/19 38/38/38 20/20/20
f 19/19/19 37/37/37 38/38/38
f 18/18/18 37/37/37 19/19/19
f 1/1/1 37/37/37 18/18/18
f 37/37/37 42/42/42 38/38/38
f 38/38/38 42/42/42 41/41/41
f 38/38/38 41/41/41 39/39/39
f 39/39/39 41/41/41 40/40/40
f 46/46/46 16/16/16 17/17/17
f 47/47/47 16/16/16 46/46/46
f 47/47/47 36/36/36 16/16/16
f 48/48/48 36/36/36 47/47/47
f 30/30/30 36/36/36 48/48/48
f 43/43/43 30/30/30 48/48/48
f 29/29/29 30/30/30 43/43/43
f 28/28/28 29/29/29 43/43/43
f 28/28/28 43/43/43 23/23/23
f 23/23/23 43/43/43 44/44/44
f 23/23/23 44/44/44 24/24/24
f 24/24/24 44/44/44 45/45/45
f 24/24/24 45/45/45 25/25/25
f 25/25/25 45/45/45 26/26/26
f 45/45/45 46/46/46 26/26/26
f 26/26/26 46/46/46 27/27/27
f 46/46/46 17/17/17 27/27/27
f 45/45/45 47/47/47 46/46/46
f 48/48/48 47/47/47 45/45/45
f 44/44/44 48/48/48 45/45/45
f 43/43/43 48/48/48 44/44/44
f 21/21/21 22/22/22 24/24/24
f 22/22/22 23/23/23 24/24/24
f 22/22/22 28/28/28 23/23/23
f 30/30/30 32/32/32 31/31/31
f 30/30/30 31/31/31 36/36/36
f 31/31/31 32/32/32 33/33/33
f 31/31/31 33/33/33 34/34/34
f 31/31/31 34/34/34 35/35/35
f 31/31/31 35/35/35 36/36/36
f 2/2/2 3/3/3 32/32/32
f 3/3/3 4/4/4 32/32/32
f 36/36/36 15/15/15 16/16/16
f 36/36/36 14/14/14 15/15/15
f 34/34/34 51/51/51 52/52/52
f 33/33/33 51/51/51 34/34/34
f 32/32/32 51/51/51 33/33/33
f 32/32/32 50/50/50 51/51/51
f 32/32/32 49/49/49 50/50/50
f 4/4/4 49/49/49 32/32/32
f 4/4/4 5/5/5 49/49/49
f 5/5/5 6/6/6 49/49/49
f 49/49/49 6/6/6 60/60/60
f 6/6/6 7/7/7 60/60/60
f 60/60/60 7/7/7 59/59/59
f 59/59/59 7/7/7 8/8/8
f 59/59/59 8/8/8 58/58/58
f 58/58/58 8/8/8 9/9/9
f 58/58/58 9/9/9 10/10/10
f 58/58/58 10/10/10 57/57/57
f 57/57/57 10/10/10 11/11/11
f 57/57/57 11/11/11 56/56/56
f 56/56/56 11/11/11 12/12/12
f 56/56/56 12/12/12 55/55/55
f 55/55/55 12/12/12 13/13/13
f 55/55/55 13/13/13 14/14/14
f 36/36/36 55/55/55 14/14/14
f 36/36/36 54/54/54 55/55/55
f 36/36/36 53/53/53 54/54/54
f 35/35/35 53/53/53 36/36/36
f 34/34/34 53/53/53 35/35/35
f 34/34/34 52/52/52 53/53/53
f 49/49/49 61/61/61 50/50/50
f 49/49/49 60/60/60 61/61/61
f 50/50/50 62/62/62 51/51/51
f 50/50/50 61/61/61 62/62/62
f 61/61/61 60/60/60 68/68/68
f 60/60/60 59/59/59 68/68/68
f 51/51/51 62/62/62 52/52/52
f 52/52/52 62/62/62 63/63/63
f 68/68/68 59/59/59 67/67/67
f 67/67/67 59/59/59 58/58/58
f 52/52/52 64/64/64 53/53/53
f 52/52/52 63/63/63 64/64/64
f 67/67/67 57/57/57 66/66/66
f 67/67/67 58/58/58 57/57/57
f 53/53/53 64/64/64 54/54/54
f 54/54/54 64/64/64 65/65/65
f 66/66/66 56/56/56 65/65/65
f 66/66/66 57/57/57 56/56/56
f 54/54/54 65/65/65 55/55/55
f 65/65/65 56/56/56 55/55/55

Просмотреть файл

@ -0,0 +1,77 @@
fileFormatVersion: 2
guid: b87e7b82bde36d14b8be320b8772fea7
timeCreated: 1483122680
licenseType: Free
ModelImporter:
serializedVersion: 18
fileIDToRecycleName:
100000: //RootNode
100002: FaceMesh
100004: DlibFaceLandmark68Mesh
400000: //RootNode
400002: FaceMesh
400004: DlibFaceLandmark68Mesh
2300000: FaceMesh
2300002: DlibFaceLandmark68Mesh
3300000: FaceMesh
3300002: DlibFaceLandmark68Mesh
4300000: FaceMesh
4300002: DlibFaceLandmark68Mesh
materials:
importMaterials: 0
materialName: 0
materialSearch: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
optimizeGameObjects: 0
motionNodeName:
animationCompression: 1
animationRotationError: .5
animationPositionError: .5
animationScaleError: .5
animationWrapMode: 0
extraExposedTransformPaths: []
clipAnimations: []
isReadable: 1
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
importBlendShapes: 0
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
optimizeMeshForGPU: 0
keepQuads: 0
weldVertices: 1
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVPackMargin: 4
useFileScale: 1
tangentSpace:
normalSmoothAngle: 60
splitTangentsAcrossUV: 0
normalImportMode: 0
tangentImportMode: 1
importAnimation: 1
copyAvatar: 0
humanDescription:
human: []
skeleton: []
armTwist: .5
foreArmTwist: .5
upperLegTwist: .5
legTwist: .5
armStretch: .0500000007
legStretch: .0500000007
feetSpacing: 0
rootMotionBoneName:
lastHumanDescriptionAvatarSource: {instanceID: 0}
animationType: 0
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
FaceMaskSample/Resources/LoadingIcon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.8 KiB

Просмотреть файл

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: 930bad9a49e0e4d4f953e03509cea6ad
timeCreated: 1481920749
licenseType: Free
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: 0
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: 0
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
FaceMaskSample/Resources/face_mask1.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 127 KiB

Просмотреть файл

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: 15fcadce448f349488a1b74f026ce010
timeCreated: 1483294900
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 1
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: 4
maxTextureSize: 512
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 0
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: 5
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
FaceMaskSample/Resources/face_mask2.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 126 KiB

Просмотреть файл

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: 7777667c554b97c4cbe1120b7dcea0a4
timeCreated: 1483294901
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 1
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: 4
maxTextureSize: 512
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 0
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: 5
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
FaceMaskSample/Resources/face_mask3.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 148 KiB

Просмотреть файл

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: 48eaa7a1d574ef647af0a2e1834f7250
timeCreated: 1483294901
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 1
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: 4
maxTextureSize: 512
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 0
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: 5
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
FaceMaskSample/Resources/face_mask4.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 112 KiB

Просмотреть файл

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: 4fd4dcb14f9983446b7b67f68114e9ba
timeCreated: 1483294901
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 1
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: 4
maxTextureSize: 512
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 0
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: 5
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
FaceMaskSample/Resources/face_mask5.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 134 KiB

Просмотреть файл

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: b1d066fd26876b04c9d7f88c65d0a68a
timeCreated: 1483294901
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 1
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: 4
maxTextureSize: 512
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 0
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: 5
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
FaceMaskSample/Resources/family.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 MiB

Просмотреть файл

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: 4796bf2415d8dc146b669a2d8680f963
timeCreated: 1481920749
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 1
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: 4
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 0
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: 5
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: c7ad3f05dc719a0439f11658cf226ca5
folderAsset: yes
timeCreated: 1481920838
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e6b1c061d75dec44b8b04657ceef9ee9
timeCreated: 1481920838
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 47d6f4267b82db945b369373fdaa8fed
timeCreated: 1481920838
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 070ebc21b7e5e204f82421ed10dbe8dc
timeCreated: 1481920838
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5c77f16fe1d24ce4dab1f841c0eac8df
timeCreated: 1481920838
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 63f1fb189940f464fbdb7d5b31d3eb06
timeCreated: 1481920838
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 81e7dc48b1dc0684c94514c609651308
folderAsset: yes
timeCreated: 1481920838
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 172e02f113885e441808191b26575189
folderAsset: yes
timeCreated: 1483198025
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,237 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FaceMaskSample
{
public static class SampleDataSet
{
private static int index = 0;
public static int Index
{
get { return index; }
}
public static int Length
{
get { return filenames.Length; }
}
private static string[] filenames = new string[5]{
"face_mask1",
"face_mask2",
"face_mask3",
"face_mask4",
"face_mask5"
};
private static Rect[] faceRcts = new Rect[5]{
new Rect(),
new Rect(),
new Rect(),
//panda
new Rect(17, 64, 261, 205),
//anime
new Rect(56, 85, 190, 196)
};
private static List<Vector2>[] landmarkPoints = new List<Vector2>[5]{
null,
null,
null,
//panda
new List<Vector2>(){
new Vector2(31, 136),
new Vector2(23, 169),
new Vector2(26, 195),
new Vector2(35, 216),
new Vector2(53, 236),
new Vector2(71, 251),
new Vector2(96, 257),
new Vector2(132, 259),
new Vector2(143, 263),
//9
new Vector2(165, 258),
new Vector2(198, 255),
new Vector2(222, 242),
new Vector2(235, 231),
new Vector2(248, 215),
new Vector2(260, 195),
new Vector2(272, 171),
new Vector2(264, 135),
//17
new Vector2(45, 115),
new Vector2(70, 94),
new Vector2(97, 89),
new Vector2(116, 90),
new Vector2(135, 105),
new Vector2(157, 104),
new Vector2(176, 90),
new Vector2(198, 86),
new Vector2(223, 90),
new Vector2(248, 110),
//27
new Vector2(148, 134),
new Vector2(147, 152),
new Vector2(145, 174),
new Vector2(144, 192),
new Vector2(117, 205),
new Vector2(128, 213),
new Vector2(143, 216),
new Vector2(160, 216),
new Vector2(174, 206),
//36
new Vector2(96, 138),
new Vector2(101, 131),
new Vector2(111, 132),
new Vector2(114, 140),
new Vector2(109, 146),
new Vector2(100, 146),
new Vector2(180, 138),
new Vector2(186, 130),
new Vector2(195, 131),
new Vector2(199, 137),
new Vector2(195, 143),
new Vector2(185, 143),
//48
new Vector2(109, 235),
new Vector2(118, 231),
new Vector2(129, 228),
new Vector2(143, 225),
new Vector2(156, 227),
new Vector2(174, 232),
new Vector2(181, 234),
new Vector2(173, 241),
new Vector2(156, 245),
new Vector2(143, 245),
new Vector2(130, 244),
new Vector2(117, 239),
new Vector2(114, 235),
new Vector2(130, 232),
new Vector2(142, 232),
new Vector2(157, 233),
new Vector2(175, 236),
new Vector2(155, 237),
new Vector2(143, 238),
new Vector2(130, 237)
},
//anime
new List<Vector2>(){
new Vector2(62, 179),
new Vector2(72, 209),
new Vector2(75, 223),
new Vector2(81, 236),
new Vector2(90, 244),
new Vector2(101, 251),
new Vector2(116, 258),
new Vector2(129, 262),
new Vector2(142, 268),
new Vector2(160, 265),
new Vector2(184, 260),
new Vector2(202, 253),
new Vector2(210, 247),
new Vector2(217, 239),
new Vector2(222, 229),
new Vector2(225, 222),
new Vector2(243, 191),
//17
new Vector2(68, 136),
new Vector2(86, 128),
new Vector2(104, 126),
new Vector2(122, 131),
new Vector2(134, 141),
new Vector2(177, 143),
new Vector2(191, 135),
new Vector2(209, 132),
new Vector2(227, 136),
new Vector2(239, 143),
//27
new Vector2(153, 163),
new Vector2(150, 190),
new Vector2(149, 201),
new Vector2(148, 212),
new Vector2(138, 217),
new Vector2(141, 219),
new Vector2(149, 221),
new Vector2(152, 220),
new Vector2(155, 217),
//36
new Vector2(70, 182),
new Vector2(85, 165),
new Vector2(114, 168),
new Vector2(122, 192),
new Vector2(113, 211),
new Vector2(82, 209),
new Vector2(177, 196),
new Vector2(189, 174),
new Vector2(220, 175),
new Vector2(234, 192),
new Vector2(215, 220),
new Vector2(184, 217),
//48
new Vector2(132, 249),
new Vector2(134, 249),
new Vector2(139, 250),
new Vector2(144, 251),
new Vector2(148, 251),
new Vector2(153, 250),
new Vector2(155, 251),
new Vector2(154, 253),
new Vector2(149, 257),
new Vector2(144, 257),
new Vector2(138, 256),
new Vector2(133, 252),
new Vector2(133, 250),
new Vector2(139, 252),
new Vector2(144, 254),
new Vector2(148, 253),
new Vector2(153, 251),
new Vector2(148, 254),
new Vector2(144, 254),
new Vector2(139, 253),
}
};
public static SampleMaskData GetData(){
return new SampleMaskData(filenames[index], faceRcts[index], landmarkPoints[index]);
}
public static SampleMaskData GetData(int index){
return new SampleMaskData(filenames[index], faceRcts[index], landmarkPoints[index]);
}
public static void Next(){
index++;
if(index == filenames.Length)
index = 0;
}
}
public class SampleMaskData
{
private string filename;
public string FileName
{
get { return this.filename; }
}
private Rect faceRect;
public Rect FaceRect
{
get { return this.faceRect; }
}
private List<Vector2> landmarkPoints;
public List<Vector2> LandmarkPoints
{
get { return this.landmarkPoints; }
}
public SampleMaskData(string filename, Rect faceRect, List<Vector2> landmarkPoints){
this.filename = filename;
this.faceRect = faceRect;
this.landmarkPoints = landmarkPoints;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7c80dd142a6fcc744a2f10f3a3aa4d49
timeCreated: 1483125206
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,64 @@
using UnityEngine;
using System.Collections;
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
using UnityEngine.SceneManagement;
#endif
namespace FaceMaskSample
{
/// <summary>
/// Face mask sample.
/// </summary>
public class FaceMaskSample : 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 OnTexture2DFaceMaskSample ()
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
SceneManager.LoadScene ("Texture2DFaceMaskSample");
#else
Application.LoadLevel ("Texture2DFaceMaskSample");
#endif
}
public void OnVideoCaptureFaceMaskSample ()
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
SceneManager.LoadScene ("VideoCaptureFaceMaskSample");
#else
Application.LoadLevel ("VideoCaptureFaceMaskSample");
#endif
}
public void OnWebCamTextureFaceMaskSample ()
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
SceneManager.LoadScene ("WebCamTextureFaceMaskSample");
#else
Application.LoadLevel ("WebCamTextureFaceMaskSample");
#endif
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: facc282ddcd086e46a52c5e4dee1cb0e
timeCreated: 1481920838
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: b40af3c3b03f5ef4d9d20289b6781a69
folderAsset: yes
timeCreated: 1481980040
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,139 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FaceMaskSample
{
public class ObjectPool : MonoBehaviour
{
public GameObject prefab;
public int maxCount = 100;
public int prepareCount = 0;
[SerializeField]
private int interval = 1;
private List<GameObject> pooledObjectList = new List<GameObject>();
private IEnumerator removeObjectCheckCoroutine;
void OnEnable()
{
if (interval > 0){
removeObjectCheckCoroutine = RemoveObjectCheck();
StartCoroutine(removeObjectCheckCoroutine);
}
}
void OnDisable()
{
if (removeObjectCheckCoroutine != null){
StopCoroutine(removeObjectCheckCoroutine);
removeObjectCheckCoroutine = null;
}
}
void OnDestroy()
{
DestroyAllObjects ();
}
public int Interval
{
get
{
return interval;
}
set
{
if (interval != value)
{
interval = value;
if (removeObjectCheckCoroutine != null){
StopCoroutine(removeObjectCheckCoroutine);
removeObjectCheckCoroutine = null;
}
if (interval > 0){
removeObjectCheckCoroutine = RemoveObjectCheck();
StartCoroutine(removeObjectCheckCoroutine);
}
}
}
}
public GameObject GetInstance()
{
return GetInstance(transform);
}
public GameObject GetInstance(Transform parent)
{
if (prefab == null){
Debug.LogWarning("prefab object is not set.");
return null;
}
pooledObjectList.RemoveAll((obj) => obj == null);
foreach (GameObject obj in pooledObjectList)
{
if (obj.activeSelf == false)
{
obj.SetActive(true);
return obj;
}
}
if (pooledObjectList.Count < maxCount)
{
GameObject obj = (GameObject)GameObject.Instantiate(prefab);
obj.SetActive(true);
obj.transform.parent = parent;
pooledObjectList.Add(obj);
return obj;
}
return null;
}
IEnumerator RemoveObjectCheck()
{
while (true)
{
RemoveObject(prepareCount);
yield return new WaitForSeconds(interval);
}
}
public void RemoveObject(int max)
{
if (pooledObjectList.Count > max)
{
int needRemoveCount = pooledObjectList.Count - max;
foreach (GameObject obj in pooledObjectList.ToArray())
{
if (needRemoveCount == 0)
{
break;
}
if (obj.activeSelf == false)
{
pooledObjectList.Remove(obj);
Destroy(obj);
needRemoveCount--;
}
}
}
}
public void DestroyAllObjects ()
{
foreach (var obj in pooledObjectList)
{
Destroy(obj);
}
pooledObjectList.Clear();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 26c6457357aaf0541a7914ce67900b0e
timeCreated: 1481980241
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,66 @@
using System;
using UnityEngine;
namespace FaceMaskSample
{
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter), typeof(MeshCollider))]
public class TrackedMesh : MonoBehaviour
{
private MeshFilter meshFilter;
private MeshRenderer meshRenderer;
private MeshCollider meshCollider;
public MeshFilter MeshFilter
{
get { return meshFilter; }
}
public MeshRenderer MeshRenderer
{
get { return meshRenderer; }
}
public MeshCollider MeshCollider
{
get { return meshCollider; }
}
public int Id
{
get { return id; }
set { id = value; }
}
private int id = 0;
public Material Material
{
get { return material; }
}
private Material material;
void Awake()
{
meshFilter = this.GetComponent<MeshFilter>();
meshRenderer = this.GetComponent<MeshRenderer>();
meshCollider = this.GetComponent<MeshCollider>();
if (meshRenderer.material == null)
throw new Exception("Material does not exist.");
material = meshRenderer.material;
}
void OnDestroy(){
if(meshFilter != null && meshFilter.mesh != null){
DestroyImmediate(meshFilter.mesh);
}
if(meshRenderer != null && meshRenderer.materials != null){
foreach(var m in meshRenderer.materials){
DestroyImmediate(m);
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c47754ddde934e14c95f9de06ad6413d
timeCreated: 1481980241
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,210 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using OpenCVForUnity.RectangleTrack;
namespace FaceMaskSample
{
public class TrackedMeshOverlay : MonoBehaviour
{
public int Interval = 1;
public int PoolSize = 10;
[SerializeField]
private GameObject baseObject;
public GameObject BaseObject
{
get {
return baseObject;
}
set {
baseObject = value;
setBaseObject(baseObject);
}
}
public float Width
{
get {
return targetWidth;
}
}
public float Height
{
get {
return targetHeight;
}
}
protected Transform targetTransform;
protected float targetWidth = 0;
protected float targetHeight = 0;
protected Transform overlayTransform;
protected ObjectPool objectPool;
protected Dictionary<int, TrackedMesh> showingObjects = new Dictionary<int, TrackedMesh>();
void Awake()
{
init("MeshOverlay");
}
void OnDestroy()
{
overlayTransform = null;
targetTransform = null;
targetWidth = 0;
targetHeight = 0;
showingObjects.Clear();
if(objectPool != null)
{
Destroy(objectPool.gameObject);
objectPool = null;
}
}
protected GameObject getPoolObject(Transform parent)
{
if(objectPool == null) return null;
GameObject newObj = objectPool.GetInstance(parent);
if(newObj != null){
newObj.transform.parent = parent;
return newObj;
}else{
return null;
}
}
protected virtual void init(String name)
{
GameObject obj = new GameObject(name);
overlayTransform = obj.transform;
overlayTransform.parent = gameObject.transform.parent;
UpdateOverlayTransform();
if(baseObject != null)
setBaseObject (baseObject);
}
protected virtual void setBaseObject (GameObject obj)
{
if (obj.GetComponent<TrackedMesh>() == null)
{
Debug.LogWarning("Object is not TrackedMesh.");
return;
}
if(objectPool != null){
Destroy(objectPool);
}
objectPool = overlayTransform.gameObject.AddComponent<ObjectPool>();
objectPool.prefab = obj;
objectPool.maxCount = PoolSize;
objectPool.prepareCount = (int)PoolSize / 2;
objectPool.Interval = Interval;
}
public virtual void UpdateOverlayTransform(Transform targetTransform)
{
if (targetTransform == null)
{
this.targetTransform = null;
return;
}
targetWidth = targetTransform.localScale.x;
targetHeight = targetTransform.localScale.y;
this.targetTransform = targetTransform;
overlayTransform.localPosition = new Vector3(targetTransform.localPosition.x, targetTransform.localPosition.y, targetTransform .localPosition.z - 0.1f);
}
public virtual void UpdateOverlayTransform()
{
Renderer renderer = gameObject.GetComponent<Renderer>();
if(renderer == null) return;
targetWidth = renderer.bounds.size.x;
targetHeight = renderer.bounds.size.y;
Vector3 center = renderer.bounds.center;
Debug.Log(targetWidth + " " + targetHeight + " " + center);
overlayTransform.localPosition = new Vector3(center.x, center.y, center.z - 0.1f);
}
public virtual TrackedMesh GetObjectById(int id)
{
if (showingObjects.ContainsKey(id))
{
return showingObjects[id];
}
return null;
}
public virtual TrackedMesh CreateObject(int id, Texture2D tex = null)
{
if (!showingObjects.ContainsKey(id)){
GameObject obj = getPoolObject(overlayTransform);
if (obj == null) return null;
TrackedMesh tm = obj.GetComponent<TrackedMesh>();
if (tm != null)
{
tm.Id = id;
tm.transform.localPosition = new Vector3(0, 0, 0);
tm.transform.localRotation = new Quaternion();
tm.transform.localScale = new Vector3(1, 1, 1);
if (tex != null) tm.Material.mainTexture = tex;
showingObjects.Add(id, tm);
}
return tm;
}
else{
return null;
}
}
public virtual void UpdateObject(int id, Vector3[] vertices, int[] triangles = null, Vector2[] uv = null)
{
if (showingObjects.ContainsKey(id)){
TrackedMesh tm = showingObjects[id];
if(vertices.Length != tm.MeshFilter.mesh.vertices.Length) Debug.LogError("The number of vertices does not match.");
tm.MeshFilter.mesh.vertices = vertices;
if (triangles != null)
{
tm.MeshFilter.mesh.triangles = triangles;
}
if (uv != null)
{
tm.MeshFilter.mesh.uv = uv;
}
tm.MeshFilter.mesh.RecalculateBounds();
tm.MeshFilter.mesh.RecalculateNormals();
}
}
public virtual void DeleteObject(int id)
{
if (showingObjects.ContainsKey(id))
{
if(showingObjects[id] != null)
showingObjects[id].gameObject.SetActive(false);
showingObjects.Remove(id);
}
}
public virtual void Reset()
{
foreach (int key in showingObjects.Keys)
{
if(showingObjects[key] != null)
showingObjects[key].gameObject.SetActive(false);
}
showingObjects.Clear();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 59726869b6e135846a8945aadc9b78d9
timeCreated: 1481980241
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,38 @@
using UnityEngine;
using System.Collections;
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
using UnityEngine.SceneManagement;
#endif
namespace FaceMaskSample
{
/// <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 ("FaceMaskSample");
#else
Application.LoadLevel ("FaceMaskSample");
#endif
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4b8251a771a9a044bb64efaf0fa43495
timeCreated: 1481920838
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,432 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using DlibFaceLandmarkDetector;
using OpenCVForUnity;
using WebGLFileUploader;
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
using UnityEngine.SceneManagement;
#endif
namespace FaceMaskSample
{
/// <summary>
/// Texture2D face mask sample.
/// </summary>
public class Texture2DFaceMaskSample : MonoBehaviour
{
/// <summary>
/// The image texture.
/// </summary>
Texture2D imgTexture;
/// <summary>
/// The cascade.
/// </summary>
CascadeClassifier cascade;
/// <summary>
/// The face landmark detector.
/// </summary>
FaceLandmarkDetector faceLandmarkDetector;
/// <summary>
/// The is showing face rects.
/// </summary>
public bool isShowingFaceRects = false;
/// <summary>
/// The is showing face rects toggle.
/// </summary>
public Toggle isShowingFaceRectsToggle;
/// <summary>
/// The use Dlib face detector flag.
/// </summary>
public bool useDlibFaceDetecter = true;
/// <summary>
/// The use dlib face detecter toggle.
/// </summary>
public Toggle useDlibFaceDetecterToggle;
/// <summary>
/// The is filtering non frontal faces.
/// </summary>
public bool isFilteringNonFrontalFaces;
/// <summary>
/// The is filtering non frontal faces toggle.
/// </summary>
public Toggle isFilteringNonFrontalFacesToggle;
/// <summary>
/// The frontal face rate lower limit.
/// </summary>
[Range (0.0f, 1.0f)]
public float
frontalFaceRateLowerLimit = 0.85f;
/// <summary>
/// The is showing debug face points.
/// </summary>
public bool isShowingDebugFacePoints = false;
/// <summary>
/// The is showing debug face points toggle.
/// </summary>
public Toggle isShowingDebugFacePointsToggle;
/// <summary>
/// The is upload image button.
/// </summary>
public Button uploadImageButton;
/// <summary>
/// The mesh overlay.
/// </summary>
private TrackedMeshOverlay meshOverlay;
/// <summary>
/// The haarcascade_frontalface_alt_xml_filepath.
/// </summary>
private string haarcascade_frontalface_alt_xml_filepath;
/// <summary>
/// The shape_predictor_68_face_landmarks_dat_filepath.
/// </summary>
private string shape_predictor_68_face_landmarks_dat_filepath;
// Use this for initialization
void Start ()
{
WebGLFileUploadManager.SetImageEncodeSetting (true);
WebGLFileUploadManager.SetAllowedFileName ("\\.(png|jpe?g|gif)$");
WebGLFileUploadManager.SetImageShrinkingSize (640, 480);
WebGLFileUploadManager.FileUploadEventHandler += fileUploadHandler;
#if UNITY_WEBGL && !UNITY_EDITOR
StartCoroutine(getFilePathCoroutine());
#else
haarcascade_frontalface_alt_xml_filepath = OpenCVForUnity.Utils.getFilePath ("haarcascade_frontalface_alt.xml");
shape_predictor_68_face_landmarks_dat_filepath = DlibFaceLandmarkDetector.Utils.getFilePath ("shape_predictor_68_face_landmarks.dat");
Run ();
#endif
}
#if UNITY_WEBGL && !UNITY_EDITOR
private IEnumerator getFilePathCoroutine ()
{
var getFilePathAsync_0_Coroutine = StartCoroutine (OpenCVForUnity.Utils.getFilePathAsync ("haarcascade_frontalface_alt.xml", (result) => {
haarcascade_frontalface_alt_xml_filepath = result;
}));
var getFilePathAsync_1_Coroutine = StartCoroutine (DlibFaceLandmarkDetector.Utils.getFilePathAsync ("shape_predictor_68_face_landmarks.dat", (result) => {
shape_predictor_68_face_landmarks_dat_filepath = result;
}));
yield return getFilePathAsync_0_Coroutine;
yield return getFilePathAsync_1_Coroutine;
Run ();
uploadImageButton.interactable = true;
}
#endif
private void Run ()
{
meshOverlay = this.GetComponent<TrackedMeshOverlay> ();
isShowingFaceRectsToggle.isOn = isShowingFaceRects;
useDlibFaceDetecterToggle.isOn = useDlibFaceDetecter;
isFilteringNonFrontalFacesToggle.isOn = isFilteringNonFrontalFaces;
isShowingDebugFacePointsToggle.isOn = isShowingDebugFacePoints;
if (imgTexture == null)
imgTexture = Resources.Load ("family") as Texture2D;
gameObject.transform.localScale = new Vector3 (imgTexture.width, imgTexture.height, 1);
Debug.Log ("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
meshOverlay.UpdateOverlayTransform ();
meshOverlay.Reset ();
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;
}
Mat rgbaMat = new Mat (imgTexture.height, imgTexture.width, CvType.CV_8UC4);
OpenCVForUnity.Utils.texture2DToMat (imgTexture, rgbaMat);
Debug.Log ("rgbaMat ToString " + rgbaMat.ToString ());
if (faceLandmarkDetector == null)
faceLandmarkDetector = new FaceLandmarkDetector (shape_predictor_68_face_landmarks_dat_filepath);
FrontalFaceParam frontalFaceParam = new FrontalFaceParam ();
// face detection.
List<OpenCVForUnity.Rect> detectResult = new List<OpenCVForUnity.Rect> ();
if (useDlibFaceDetecter) {
OpenCVForUnityUtils.SetImage (faceLandmarkDetector, rgbaMat);
List<UnityEngine.Rect> result = faceLandmarkDetector.Detect ();
foreach (var unityRect in result) {
detectResult.Add (new OpenCVForUnity.Rect ((int)unityRect.x, (int)unityRect.y, (int)unityRect.width, (int)unityRect.height));
}
} else {
if (cascade == null)
cascade = new CascadeClassifier (haarcascade_frontalface_alt_xml_filepath);
if (cascade.empty ()) {
Debug.LogError ("cascade file is not loaded.Please copy from “FaceTrackerSample/StreamingAssets/” to “Assets/StreamingAssets/” folder. ");
}
// convert image to greyscale.
Mat gray = new Mat ();
Imgproc.cvtColor (rgbaMat, gray, Imgproc.COLOR_RGBA2GRAY);
// detect Faces.
MatOfRect faces = new MatOfRect ();
Imgproc.equalizeHist (gray, gray);
cascade.detectMultiScale (gray, faces, 1.1f, 2, 0 | Objdetect.CASCADE_SCALE_IMAGE, new OpenCVForUnity.Size (gray.cols () * 0.05, gray.cols () * 0.05), new Size ());
//Debug.Log ("faces " + faces.dump ());
detectResult = faces.toList ();
// Adjust to Dilb's result.
foreach (OpenCVForUnity.Rect r in detectResult) {
r.y += (int)(r.height * 0.1f);
}
gray.Dispose ();
}
// detect face landmark.
OpenCVForUnityUtils.SetImage (faceLandmarkDetector, rgbaMat);
List<List<Vector2>> landmarkPoints = new List<List<Vector2>> ();
foreach (var openCVRect in detectResult) {
UnityEngine.Rect rect = new UnityEngine.Rect (openCVRect.x, openCVRect.y, openCVRect.width, openCVRect.height);
Debug.Log ("face : " + rect);
//OpenCVForUnityUtils.DrawFaceRect(imgMat, rect, new Scalar(255, 0, 0, 255), 2);
List<Vector2> points = faceLandmarkDetector.DetectLandmark (rect);
//OpenCVForUnityUtils.DrawFaceLandmark(imgMat, points, new Scalar(0, 255, 0, 255), 2);
landmarkPoints.Add (points);
}
// mask faces.
int[] face_nums = new int[landmarkPoints.Count];
for (int i = 0; i < face_nums.Length; i++) {
face_nums [i] = i;
}
face_nums = face_nums.OrderBy (i => System.Guid.NewGuid ()).ToArray ();
float offsetX = meshOverlay.Width / 2f;
float offsetY = meshOverlay.Height / 2f;
float maskImageWidth = imgTexture.width;
float maskImageHeight = imgTexture.height;
TrackedMesh tm;
for (int i = 0; i < face_nums.Length; i++) {
meshOverlay.CreateObject (i, imgTexture);
tm = meshOverlay.GetObjectById (i);
Vector3[] vertices = tm.MeshFilter.mesh.vertices;
if (vertices.Length == landmarkPoints [face_nums [i]].Count) {
for (int j = 0; j < vertices.Length; j++) {
vertices [j].x = landmarkPoints [face_nums [i]] [j].x - offsetX;
vertices [j].y = offsetY - landmarkPoints [face_nums [i]] [j].y;
}
}
Vector2[] uv = tm.MeshFilter.mesh.uv;
if (uv.Length == landmarkPoints [face_nums [0]].Count) {
for (int jj = 0; jj < uv.Length; jj++) {
uv [jj].x = landmarkPoints [face_nums [0]] [jj].x / maskImageWidth;
uv [jj].y = (maskImageHeight - landmarkPoints [face_nums [0]] [jj].y) / maskImageHeight;
}
}
meshOverlay.UpdateObject (i, vertices, null, uv);
// filter nonfrontalface.
if (isFilteringNonFrontalFaces && frontalFaceParam.getFrontalFaceRate (landmarkPoints [i]) < frontalFaceRateLowerLimit) {
tm.Material.SetFloat ("_Fade", 1f);
} else {
tm.Material.SetFloat ("_Fade", 0.3f);
}
}
// draw face rects.
if (isShowingFaceRects) {
int ann = face_nums[0];
UnityEngine.Rect rect_ann = new UnityEngine.Rect (detectResult [ann].x, detectResult [ann].y, detectResult [ann].width, detectResult [ann].height);
OpenCVForUnityUtils.DrawFaceRect (rgbaMat, rect_ann, new Scalar (255, 255, 0, 255), 2);
int bob = 0;
for (int i = 1; i < face_nums.Length; i ++) {
bob = face_nums [i];
UnityEngine.Rect rect_bob = new UnityEngine.Rect (detectResult [bob].x, detectResult [bob].y, detectResult [bob].width, detectResult [bob].height);
OpenCVForUnityUtils.DrawFaceRect (rgbaMat, rect_bob, new Scalar (255, 0, 0, 255), 2);
}
}
// draw face points.
if (isShowingDebugFacePoints) {
for (int i = 0; i < landmarkPoints.Count; i++) {
OpenCVForUnityUtils.DrawFaceLandmark (rgbaMat, landmarkPoints [i], new Scalar (0, 255, 0, 255), 2);
}
}
Texture2D texture = new Texture2D (rgbaMat.cols (), rgbaMat.rows (), TextureFormat.RGBA32, false);
OpenCVForUnity.Utils.matToTexture2D (rgbaMat, texture);
gameObject.transform.GetComponent<Renderer> ().material.mainTexture = texture;
frontalFaceParam.Dispose ();
rgbaMat.Dispose ();
}
/// <summary>
/// Raises the destroy event.
/// </summary>
void OnDestroy ()
{
WebGLFileUploadManager.FileUploadEventHandler -= fileUploadHandler;
WebGLFileUploadManager.Dispose ();
if (faceLandmarkDetector != null)
faceLandmarkDetector.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 ("FaceMaskSample");
#else
Application.LoadLevel ("FaceMaskSample");
#endif
}
/// <summary>
/// Raises the shuffle button event.
/// </summary>
public void OnShuffleButton ()
{
if (imgTexture != null)
Run ();
}
/// <summary>
/// Raises the is showing face rects toggle event.
/// </summary>
public void OnIsShowingFaceRectsToggle ()
{
if (isShowingFaceRectsToggle.isOn) {
isShowingFaceRects = true;
} else {
isShowingFaceRects = false;
}
if (imgTexture != null)
Run ();
}
/// <summary>
/// Raises the use Dlib face detector toggle event.
/// </summary>
public void OnUseDlibFaceDetecterToggle ()
{
if (useDlibFaceDetecterToggle.isOn) {
useDlibFaceDetecter = true;
} else {
useDlibFaceDetecter = false;
}
if (imgTexture != null)
Run ();
}
/// <summary>
/// Raises the is filtering non frontal faces toggle event.
/// </summary>
public void OnIsFilteringNonFrontalFacesToggle ()
{
if (isFilteringNonFrontalFacesToggle.isOn) {
isFilteringNonFrontalFaces = true;
} else {
isFilteringNonFrontalFaces = false;
}
if (imgTexture != null)
Run ();
}
/// <summary>
/// Raises the is showing debug face points toggle event.
/// </summary>
public void OnIsShowingDebugFacePointsToggle ()
{
if (isShowingDebugFacePointsToggle.isOn) {
isShowingDebugFacePoints = true;
} else {
isShowingDebugFacePoints = false;
}
if (imgTexture != null)
Run ();
}
/// <summary>
/// Raises the upload image button event.
/// </summary>
public void OnUploadImageButton ()
{
WebGLFileUploadManager.PopupDialog (null, "Select image file (.png|.jpg|.gif)");
}
private void fileUploadHandler (UploadedFileInfo[] result)
{
if (result.Length == 0) {
Debug.Log ("File upload Error!");
return;
}
foreach (UploadedFileInfo file in result) {
if (file.isSuccess) {
Debug.Log ("file.filePath: " + file.filePath + " exists:" + File.Exists (file.filePath));
imgTexture = new Texture2D (2, 2);
byte[] byteArray = File.ReadAllBytes (file.filePath);
imgTexture.LoadImage (byteArray);
break;
}
}
Run ();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: cd66fda4a37976f45ac5f300538ea3a5
timeCreated: 1481920838
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 296e6f34a61e0fe4cbdd1655787c3764
folderAsset: yes
timeCreated: 1483013079
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,240 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCVForUnity;
namespace FaceMaskSample
{
public class FrontalFaceParam : IDisposable
{
// Calib3d.solvePnP.
Matrix4x4 transformationM = new Matrix4x4 ();
MatOfPoint3f objectPoints;
MatOfPoint2f imagePoints;
Mat rvec;
Mat tvec;
Mat rotM;
Mat camMatrix;
MatOfDouble distCoeffs;
Matrix4x4 invertYM;
Matrix4x4 invertZM;
Matrix4x4 ARM;
// normalize.
float normWidth = 200;
float normHeight = 200;
List<Vector2> normPoints;
public FrontalFaceParam ()
{
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 ());
// 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 mouth //new Point3(-22, 17, 90),//l mouth
new Point3 (20, 15, 90),//r mouth //new Point3(22, 17, 90),//r mouth
new Point3 (-69, 76, -2),//l ear
new Point3 (69, 76, -2)//r ear
);
imagePoints = new MatOfPoint2f ();
rvec = new Mat ();
tvec = new Mat ();
rotM = new Mat (3, 3, CvType.CV_64FC1);
float max_d = Mathf.Max (normHeight, normWidth);
camMatrix = new Mat (3, 3, CvType.CV_64FC1);
camMatrix.put (0, 0, max_d);
camMatrix.put (0, 1, 0);
camMatrix.put (0, 2, normWidth / 2.0f);
camMatrix.put (1, 0, 0);
camMatrix.put (1, 1, max_d);
camMatrix.put (1, 2, normHeight / 2.0f);
camMatrix.put (2, 0, 0);
camMatrix.put (2, 1, 0);
camMatrix.put (2, 2, 1.0f);
distCoeffs = new MatOfDouble (0, 0, 0, 0);
//Debug.Log("distCoeffs " + distCoeffs.dump());
normPoints = new List<Vector2> (68);
for (int i = 0; i < 68; i++) {
normPoints.Add (new Vector2 (0, 0));
}
}
public void Dispose ()
{
objectPoints.Dispose ();
imagePoints.Dispose ();
rvec.Dispose ();
tvec.Dispose ();
rotM.Dispose ();
camMatrix.Dispose ();
distCoeffs.Dispose ();
}
/// <summary>
/// Gets the frontal face angle.
/// </summary>
/// <returns>The frontal face angle.</returns>
/// <param name="points">Points.</param>
public virtual Vector3 getFrontalFaceAngle (List<Vector2> points)
{
if (points.Count != 68)
throw new ArgumentNullException ("Invalid landmark_points.");
if (camMatrix == null)
throw new ArgumentNullException ("Invalid camMatrix.");
// normalize.
float normScale = Math.Abs (points [30].y - points [8].y) / (normHeight / 2);
Vector2 normDiff = points [30] * normScale - new Vector2 (normWidth / 2, normHeight / 2);
for (int i = 0; i < points.Count; i++) {
normPoints [i] = points [i] * normScale - normDiff;
}
// Debug.Log ("points[30] " + points[30]);
// Debug.Log ("normPoints[30] " + normPoints[30]);
// Debug.Log ("normScale " + normScale);
// Debug.Log ("normDiff " + normDiff);
imagePoints.fromArray (
new Point ((normPoints [38].x + normPoints [41].x) / 2, (normPoints [38].y + normPoints [41].y) / 2),//l eye
new Point ((normPoints [43].x + normPoints [46].x) / 2, (normPoints [43].y + normPoints [46].y) / 2),//r eye
new Point (normPoints [33].x, normPoints [33].y),//nose
new Point (normPoints [48].x, normPoints [48].y),//l mouth
new Point (normPoints [54].x, normPoints [54].y), //r mouth ,
new Point (normPoints [0].x, normPoints [0].y),//l ear
new Point (normPoints [16].x, normPoints [16].y)//r ear
);
Calib3d.solvePnP (objectPoints, imagePoints, camMatrix, distCoeffs, rvec, tvec);
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));
ARM = invertYM * transformationM * invertZM;
return ExtractRotationFromMatrix (ref ARM).eulerAngles;
}
/// <summary>
/// Gets the frontal face rate.
/// </summary>
/// <returns>The frontal face rate.</returns>
/// <param name="points">Points.</param>
public float getFrontalFaceRate (List<Vector2> points)
{
Vector3 angles = getFrontalFaceAngle (points);
float rotateX = (angles.x > 180) ? angles.x - 360 : angles.x;
float rotateY = (angles.y > 180) ? angles.y - 360 : angles.y;
// Debug.Log ("angles " + angles);
// Debug.Log ("ratio " + (1.0f - (Mathf.Max (Mathf.Abs (rotateX), Mathf.Abs (rotateY)) / 90)));
return 1.0f - (Mathf.Max (Mathf.Abs (rotateX), Mathf.Abs (rotateY)) / 90);
}
/// <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,12 @@
fileFormatVersion: 2
guid: 9ca261b0c69717b40a4763cddf124abc
timeCreated: 1481920838
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,46 @@
using UnityEngine;
using System.Collections;
using System.IO;
using System.Text;
public class ObjExporter {
public static string MeshToString(MeshFilter mf) {
Mesh m = mf.mesh;
Material[] mats = mf.GetComponent<Renderer>().sharedMaterials;
StringBuilder sb = new StringBuilder();
sb.Append("g ").Append(mf.name).Append("\n");
foreach(Vector3 v in m.vertices) {
sb.Append(string.Format("v {0} {1} {2}\n",v.x,v.y,v.z));
}
sb.Append("\n");
foreach(Vector3 v in m.normals) {
sb.Append(string.Format("vn {0} {1} {2}\n",v.x,v.y,v.z));
}
sb.Append("\n");
foreach(Vector3 v in m.uv) {
sb.Append(string.Format("vt {0} {1}\n",v.x,v.y));
}
for (int material=0; material < m.subMeshCount; material ++) {
sb.Append("\n");
sb.Append("usemtl ").Append(mats[material].name).Append("\n");
sb.Append("usemap ").Append(mats[material].name).Append("\n");
int[] triangles = m.GetTriangles(material);
for (int i=0;i<triangles.Length;i+=3) {
sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n",
triangles[i]+1, triangles[i+1]+1, triangles[i+2]+1));
}
}
return sb.ToString();
}
public static void MeshToFile(MeshFilter mf, string filename) {
using (StreamWriter sw = new StreamWriter(filename))
{
sw.Write(MeshToString(mf));
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0f4a7800f23a22c4b8f18fbc172e95d1
timeCreated: 1483013071
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,97 @@
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using OpenCVForUnity;
using DlibFaceLandmarkDetector;
namespace FaceMaskSample
{
/// <summary>
/// Utility class for the integration of DlibFaceLandmarkDetector and OpenCVForUnity.
/// </summary>
public static class OpenCVForUnityUtils
{
/// <summary>
/// Sets the image.
/// </summary>
/// <param name="faceLandmarkDetector">Face landmark detector.</param>
/// <param name="imgMat">Image mat.</param>
public static void SetImage (FaceLandmarkDetector faceLandmarkDetector, Mat imgMat)
{
if (!imgMat.isContinuous ()) {
throw new ArgumentException ("imgMat.isContinuous() must be true.");
}
faceLandmarkDetector.SetImage ((IntPtr)imgMat.dataAddr (), imgMat.width (), imgMat.height (), (int)imgMat.elemSize ());
}
/// <summary>
/// Draws the face rect.
/// </summary>
/// <param name="imgMat">Image mat.</param>
/// <param name="rect">Rect.</param>
/// <param name="color">Color.</param>
/// <param name="thickness">Thickness.</param>
public static void DrawFaceRect (Mat imgMat, UnityEngine.Rect rect, Scalar color, int thickness)
{
Imgproc.rectangle (imgMat, new Point (rect.xMin, rect.yMin), new Point (rect.xMax, rect.yMax), color, thickness);
}
/// <summary>
/// Draws the face landmark.
/// This method supports 68 landmark points.
/// </summary>
/// <param name="imgMat">Image mat.</param>
/// <param name="points">Points.</param>
/// <param name="color">Color.</param>
/// <param name="thickness">Thickness.</param>
public static void DrawFaceLandmark (Mat imgMat, List<Vector2> points, Scalar color, int thickness)
{
// //Draw the index number of facelandmark points.
// for (int i = 0; i < points.Count; i++) {
//
// Imgproc.putText (imgMat, "" + i, new Point (points [i].x, points [i].y), Core.FONT_HERSHEY_SIMPLEX, 0.4, new Scalar (0, 0, 255, 255), 1, Core.LINE_AA, false);
//
// }
if (points.Count == 68) {
for (int i = 1; i <= 16; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
for (int i = 28; i <= 30; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
for (int i = 18; i <= 21; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
for (int i = 23; i <= 26; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
for (int i = 31; i <= 35; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
Imgproc.line (imgMat, new Point (points [30].x, points [30].y), new Point (points [35].x, points [35].y), color, thickness);
for (int i = 37; i <= 41; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
Imgproc.line (imgMat, new Point (points [36].x, points [36].y), new Point (points [41].x, points [41].y), color, thickness);
for (int i = 43; i <= 47; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
Imgproc.line (imgMat, new Point (points [42].x, points [42].y), new Point (points [47].x, points [47].y), color, thickness);
for (int i = 49; i <= 59; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
Imgproc.line (imgMat, new Point (points [48].x, points [48].y), new Point (points [59].x, points [59].y), color, thickness);
for (int i = 61; i <= 67; ++i)
Imgproc.line (imgMat, new Point (points [i].x, points [i].y), new Point (points [i - 1].x, points [i - 1].y), color, thickness);
Imgproc.line (imgMat, new Point (points [60].x, points [60].y), new Point (points [67].x, points [67].y), color, thickness);
} else {
for (int i = 0; i < points.Count; i++) {
Imgproc.circle (imgMat, new Point (points [i].x, points [i].y), 2, color, -1);
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c3854081962f5bd4586e18509191e82a
timeCreated: 1481920838
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,510 @@
using OpenCVForUnity;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
namespace FaceMaskSample
{
/// <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,12 @@
fileFormatVersion: 2
guid: bafc15da02fe850489635791dda2bbdf
timeCreated: 1481920838
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,712 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using DlibFaceLandmarkDetector;
using OpenCVForUnity;
using OpenCVForUnity.RectangleTrack;
using WebGLFileUploader;
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
using UnityEngine.SceneManagement;
#endif
namespace FaceMaskSample
{
/// <summary>
/// Face Mask from VideoCapture Sample.
/// </summary>
public class VideoCaptureFaceMaskSample : MonoBehaviour
{
/// <summary>
/// The width of the frame.
/// </summary>
private double frameWidth = 320;
/// <summary>
/// The height of the frame.
/// </summary>
private double frameHeight = 240;
/// <summary>
/// The capture.
/// </summary>
VideoCapture capture;
/// <summary>
/// The rgb mat.
/// </summary>
Mat rgbMat;
/// <summary>
/// The gray mat.
/// </summary>
Mat grayMat;
/// <summary>
/// The texture.
/// </summary>
Texture2D texture;
/// <summary>
/// The cascade.
/// </summary>
CascadeClassifier cascade;
/// <summary>
/// The face landmark detector.
/// </summary>
FaceLandmarkDetector faceLandmarkDetector;
/// <summary>
/// The detection based tracker.
/// </summary>
RectangleTracker rectangleTracker;
/// <summary>
/// The frontal face parameter.
/// </summary>
FrontalFaceParam frontalFaceParam;
/// <summary>
/// The is showing face rects.
/// </summary>
public bool isShowingFaceRects = false;
/// <summary>
/// The is showing face rects toggle.
/// </summary>
public Toggle isShowingFaceRectsToggle;
/// <summary>
/// The use Dlib face detector flag.
/// </summary>
public bool useDlibFaceDetecter = true;
/// <summary>
/// The use dlib face detecter toggle.
/// </summary>
public Toggle useDlibFaceDetecterToggle;
/// <summary>
/// The is filtering non frontal faces.
/// </summary>
public bool isFilteringNonFrontalFaces;
/// <summary>
/// The is filtering non frontal faces toggle.
/// </summary>
public Toggle isFilteringNonFrontalFacesToggle;
/// <summary>
/// The frontal face rate lower limit.
/// </summary>
[Range (0.0f, 1.0f)]
public float
frontalFaceRateLowerLimit;
/// <summary>
/// The is showing debug face points.
/// </summary>
public bool isShowingDebugFacePoints = false;
/// <summary>
/// The is showing debug face points toggle.
/// </summary>
public Toggle isShowingDebugFacePointsToggle;
/// <summary>
/// The is upload face mask button.
/// </summary>
public Button uploadFaceMaskButton;
/// <summary>
/// The mesh overlay.
/// </summary>
private TrackedMeshOverlay meshOverlay;
/// <summary>
/// The Shader.PropertyToID for "_Fade".
/// </summary>
private int shader_FadeID;
/// <summary>
/// The face mask texture.
/// </summary>
private Texture2D faceMaskTexture;
/// <summary>
/// The face mask mat.
/// </summary>
private Mat faceMaskMat;
/// <summary>
/// The detected face rect in mask mat.
/// </summary>
private UnityEngine.Rect faceRectInMask;
/// <summary>
/// The detected face landmark points in mask mat.
/// </summary>
private List<Vector2> faceLandmarkPointsInMask;
/// <summary>
/// The haarcascade_frontalface_alt_xml_filepath.
/// </summary>
private string haarcascade_frontalface_alt_xml_filepath;
/// <summary>
/// The shape_predictor_68_face_landmarks_dat_filepath.
/// </summary>
private string shape_predictor_68_face_landmarks_dat_filepath;
/// <summary>
/// The couple_avi_filepath.
/// </summary>
private string couple_avi_filepath;
// Use this for initialization
void Start ()
{
WebGLFileUploadManager.SetImageEncodeSetting (true);
WebGLFileUploadManager.SetAllowedFileName ("\\.(png|jpe?g|gif)$");
WebGLFileUploadManager.SetImageShrinkingSize (640, 480);
WebGLFileUploadManager.FileUploadEventHandler += fileUploadHandler;
capture = new VideoCapture ();
#if UNITY_WEBGL && !UNITY_EDITOR
StartCoroutine(getFilePathCoroutine());
#else
haarcascade_frontalface_alt_xml_filepath = OpenCVForUnity.Utils.getFilePath ("haarcascade_frontalface_alt.xml");
shape_predictor_68_face_landmarks_dat_filepath = DlibFaceLandmarkDetector.Utils.getFilePath ("shape_predictor_68_face_landmarks.dat");
couple_avi_filepath = OpenCVForUnity.Utils.getFilePath ("dance.avi");
Run ();
#endif
}
#if UNITY_WEBGL && !UNITY_EDITOR
private IEnumerator getFilePathCoroutine()
{
var getFilePathAsync_0_Coroutine = StartCoroutine (OpenCVForUnity.Utils.getFilePathAsync ("haarcascade_frontalface_alt.xml", (result) => {
haarcascade_frontalface_alt_xml_filepath = result;
}));
var getFilePathAsync_1_Coroutine = StartCoroutine (DlibFaceLandmarkDetector.Utils.getFilePathAsync ("shape_predictor_68_face_landmarks.dat", (result) => {
shape_predictor_68_face_landmarks_dat_filepath = result;
}));
var getFilePathAsync_2_Coroutine = StartCoroutine (OpenCVForUnity.Utils.getFilePathAsync ("dance.avi", (result) => {
couple_avi_filepath = result;
}));
yield return getFilePathAsync_0_Coroutine;
yield return getFilePathAsync_1_Coroutine;
yield return getFilePathAsync_2_Coroutine;
Run ();
uploadFaceMaskButton.interactable = true;
}
#endif
private void Run ()
{
meshOverlay = this.GetComponent<TrackedMeshOverlay> ();
shader_FadeID = Shader.PropertyToID("_Fade");
rectangleTracker = new RectangleTracker ();
faceLandmarkDetector = new FaceLandmarkDetector (shape_predictor_68_face_landmarks_dat_filepath);
frontalFaceParam = new FrontalFaceParam ();
rgbMat = new Mat ();
capture.open (couple_avi_filepath);
if (capture.isOpened ()) {
Debug.Log ("capture.isOpened() true");
} else {
Debug.Log ("capture.isOpened() false");
}
Debug.Log ("CAP_PROP_FORMAT: " + capture.get (Videoio.CAP_PROP_FORMAT));
Debug.Log ("CV_CAP_PROP_PREVIEW_FORMAT: " + capture.get (Videoio.CV_CAP_PROP_PREVIEW_FORMAT));
Debug.Log ("CAP_PROP_POS_MSEC: " + capture.get (Videoio.CAP_PROP_POS_MSEC));
Debug.Log ("CAP_PROP_POS_FRAMES: " + capture.get (Videoio.CAP_PROP_POS_FRAMES));
Debug.Log ("CAP_PROP_POS_AVI_RATIO: " + capture.get (Videoio.CAP_PROP_POS_AVI_RATIO));
Debug.Log ("CAP_PROP_FRAME_COUNT: " + capture.get (Videoio.CAP_PROP_FRAME_COUNT));
Debug.Log ("CAP_PROP_FPS: " + capture.get (Videoio.CAP_PROP_FPS));
Debug.Log ("CAP_PROP_FRAME_WIDTH: " + capture.get (Videoio.CAP_PROP_FRAME_WIDTH));
Debug.Log ("CAP_PROP_FRAME_HEIGHT: " + capture.get (Videoio.CAP_PROP_FRAME_HEIGHT));
texture = new Texture2D ((int)(frameWidth), (int)(frameHeight), TextureFormat.RGBA32, false);
gameObject.transform.localScale = new Vector3 ((float)frameWidth, (float)frameHeight, 1);
float widthScale = (float)Screen.width / (float)frameWidth;
float heightScale = (float)Screen.height / (float)frameHeight;
if (widthScale < heightScale) {
Camera.main.orthographicSize = ((float)frameWidth * (float)Screen.height / (float)Screen.width) / 2;
} else {
Camera.main.orthographicSize = (float)frameHeight / 2;
}
gameObject.GetComponent<Renderer> ().material.mainTexture = texture;
meshOverlay.UpdateOverlayTransform ();
grayMat = new Mat ((int)frameHeight, (int)frameWidth, CvType.CV_8UC1);
cascade = new CascadeClassifier (haarcascade_frontalface_alt_xml_filepath);
if (cascade.empty ()) {
Debug.LogError ("cascade file is not loaded.Please copy from “FaceTrackerSample/StreamingAssets/” to “Assets/StreamingAssets/” folder. ");
}
isShowingFaceRectsToggle.isOn = isShowingFaceRects;
useDlibFaceDetecterToggle.isOn = useDlibFaceDetecter;
isFilteringNonFrontalFacesToggle.isOn = isFilteringNonFrontalFaces;
isShowingDebugFacePointsToggle.isOn = isShowingDebugFacePoints;
OnChangeFaceMaskButton ();
}
// Update is called once per frame
void Update ()
{
//Loop play
if (capture.get (Videoio.CAP_PROP_POS_FRAMES) >= capture.get (Videoio.CAP_PROP_FRAME_COUNT))
capture.set (Videoio.CAP_PROP_POS_FRAMES, 0);
//error PlayerLoop called recursively! on iOS.reccomend WebCamTexture.
if (capture.grab ()) {
capture.retrieve (rgbMat, 0);
Imgproc.cvtColor (rgbMat, rgbMat, Imgproc.COLOR_BGR2RGB);
//Debug.Log ("Mat toString " + rgbMat.ToString ());
//face detection.
List<OpenCVForUnity.Rect> detectResult = new List<OpenCVForUnity.Rect> ();
if (useDlibFaceDetecter) {
OpenCVForUnityUtils.SetImage (faceLandmarkDetector, rgbMat);
List<UnityEngine.Rect> result = faceLandmarkDetector.Detect ();
foreach (var unityRect in result) {
detectResult.Add (new OpenCVForUnity.Rect ((int)unityRect.x, (int)unityRect.y, (int)unityRect.width, (int)unityRect.height));
}
} else {
// convert image to greyscale.
Imgproc.cvtColor (rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);
using (Mat equalizeHistMat = new Mat ())
using (MatOfRect faces = new MatOfRect ()) {
Imgproc.equalizeHist (grayMat, equalizeHistMat);
cascade.detectMultiScale (equalizeHistMat, faces, 1.1f, 2, 0 | Objdetect.CASCADE_SCALE_IMAGE, new OpenCVForUnity.Size (equalizeHistMat.cols () * 0.15, equalizeHistMat.cols () * 0.15), new Size ());
detectResult = faces.toList ();
// Adjust to Dilb's result.
foreach (OpenCVForUnity.Rect r in detectResult) {
r.y += (int)(r.height * 0.1f);
}
}
}
// face traking.
rectangleTracker.UpdateTrackedObjects (detectResult);
List<TrackedRect> trackedRects = new List<TrackedRect> ();
rectangleTracker.GetObjects (trackedRects, true);
// detect face landmark.
OpenCVForUnityUtils.SetImage (faceLandmarkDetector, rgbMat);
List<List<Vector2>> landmarkPoints = new List<List<Vector2>> ();
for (int i = 0; i < trackedRects.Count; i++) {
TrackedRect tr = trackedRects [i];
UnityEngine.Rect rect = new UnityEngine.Rect (tr.x, tr.y, tr.width, tr.height);
List<Vector2> points = faceLandmarkDetector.DetectLandmark (rect);
landmarkPoints.Add (points);
}
// face masking.
if (faceMaskTexture != null && landmarkPoints.Count >= 1) {
OpenCVForUnity.Utils.texture2DToMat (faceMaskTexture, faceMaskMat);
float offsetX = meshOverlay.Width / 2f;
float offsetY = meshOverlay.Height / 2f;
float maskImageWidth = faceMaskTexture.width;
float maskImageHeight = faceMaskTexture.height;
TrackedRect tr;
TrackedMesh tm;
for (int i = 0; i < trackedRects.Count; i++) {
tr = trackedRects [i];
if (tr.state == TrackedState.NEW) {
meshOverlay.CreateObject (tr.id, faceMaskTexture);
}
if (tr.state < TrackedState.DELETED) {
tm = meshOverlay.GetObjectById (tr.id);
Vector3[] vertices = tm.MeshFilter.mesh.vertices;
if (vertices.Length == landmarkPoints [i].Count) {
for (int j = 0; j < vertices.Length; j++) {
vertices [j].x = landmarkPoints [i] [j].x - offsetX;
vertices [j].y = offsetY - landmarkPoints [i] [j].y;
}
}
Vector2[] uv = tm.MeshFilter.mesh.uv;
if (uv.Length == faceLandmarkPointsInMask.Count) {
for (int jj = 0; jj < uv.Length; jj++) {
uv [jj].x = faceLandmarkPointsInMask [jj].x / maskImageWidth;
uv [jj].y = (maskImageHeight - faceLandmarkPointsInMask [jj].y) / maskImageHeight;
}
}
meshOverlay.UpdateObject (tr.id, vertices, null, uv);
if (tr.numFramesNotDetected > 3) {
tm.Material.SetFloat (shader_FadeID, 1f);
}else if (tr.numFramesNotDetected > 0 && tr.numFramesNotDetected <= 3) {
tm.Material.SetFloat (shader_FadeID, 0.3f + (0.7f/4f) * tr.numFramesNotDetected);
} else {
tm.Material.SetFloat (shader_FadeID, 0.3f);
}
// filter nonfrontalface.
if (isFilteringNonFrontalFaces && frontalFaceParam.getFrontalFaceRate (landmarkPoints [i]) < frontalFaceRateLowerLimit) {
tm.Material.SetFloat (shader_FadeID, 1f);
}
} else if (tr.state == TrackedState.DELETED) {
meshOverlay.DeleteObject (tr.id);
}
}
} else if (landmarkPoints.Count >= 1) {
float offsetX = meshOverlay.Width / 2f;
float offsetY = meshOverlay.Height / 2f;
float maskImageWidth = texture.width;
float maskImageHeight = texture.height;
TrackedRect tr;
TrackedMesh tm;
for (int i = 0; i < trackedRects.Count; i++) {
tr = trackedRects [i];
if (tr.state == TrackedState.NEW) {
meshOverlay.CreateObject (tr.id, texture);
}
if (tr.state < TrackedState.DELETED) {
tm = meshOverlay.GetObjectById (tr.id);
Vector3[] vertices = tm.MeshFilter.mesh.vertices;
if (vertices.Length == landmarkPoints [i].Count) {
for (int j = 0; j < vertices.Length; j++) {
vertices [j].x = landmarkPoints[i][j].x - offsetX;
vertices [j].y = offsetY - landmarkPoints[i][j].y;
}
}
Vector2[] uv = tm.MeshFilter.mesh.uv;
if (uv.Length == landmarkPoints [0].Count) {
for (int jj = 0; jj < uv.Length; jj++) {
uv [jj].x = landmarkPoints[0][jj].x / maskImageWidth;
uv [jj].y = (maskImageHeight - landmarkPoints[0][jj].y) / maskImageHeight;
}
}
meshOverlay.UpdateObject (tr.id, vertices, null, uv);
if (tr.numFramesNotDetected > 3) {
tm.Material.SetFloat (shader_FadeID, 1f);
}else if (tr.numFramesNotDetected > 0 && tr.numFramesNotDetected <= 3) {
tm.Material.SetFloat (shader_FadeID, 0.3f + (0.7f/4f) * tr.numFramesNotDetected);
} else {
tm.Material.SetFloat (shader_FadeID, 0.3f);
}
// filter nonfrontalface.
if (isFilteringNonFrontalFaces && frontalFaceParam.getFrontalFaceRate (landmarkPoints [i]) < frontalFaceRateLowerLimit) {
tm.Material.SetFloat (shader_FadeID, 1f);
}
} else if (tr.state == TrackedState.DELETED) {
meshOverlay.DeleteObject (tr.id);
}
}
}
// draw face rects.
if (isShowingFaceRects) {
for (int i = 0; i < detectResult.Count; i++) {
UnityEngine.Rect rect = new UnityEngine.Rect (detectResult [i].x, detectResult [i].y, detectResult [i].width, detectResult [i].height);
OpenCVForUnityUtils.DrawFaceRect (rgbMat, rect, new Scalar (255, 0, 0, 255), 2);
}
for (int i = 0; i < trackedRects.Count; i++) {
UnityEngine.Rect rect = new UnityEngine.Rect (trackedRects [i].x, trackedRects [i].y, trackedRects [i].width, trackedRects [i].height);
OpenCVForUnityUtils.DrawFaceRect (rgbMat, rect, new Scalar (255, 255, 0, 255), 2);
//Imgproc.putText (rgbMat, " " + frontalFaceParam.getAngleOfFrontalFace (landmarkPoints [i]), new Point (rect.xMin, rect.yMin - 10), Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar (255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
//Imgproc.putText (rgbMat, " " + frontalFaceParam.getFrontalFaceRate (landmarkPoints [i]), new Point (rect.xMin, rect.yMin - 10), Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar (255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
}
}
// draw face points.
if (isShowingDebugFacePoints) {
for (int i = 0; i < landmarkPoints.Count; i++) {
OpenCVForUnityUtils.DrawFaceLandmark (rgbMat, landmarkPoints [i], new Scalar (0, 255, 0, 255), 2);
}
}
// display face mask image.
if (faceMaskTexture != null && faceMaskMat != null) {
if (isShowingFaceRects) {
OpenCVForUnityUtils.DrawFaceRect (faceMaskMat, faceRectInMask, new Scalar (255, 0, 0, 255), 2);
}
if (isShowingDebugFacePoints) {
OpenCVForUnityUtils.DrawFaceLandmark (faceMaskMat, faceLandmarkPointsInMask, new Scalar (0, 255, 0, 255), 2);
}
float scale = (rgbMat.width () / 4f) / faceMaskMat.width ();
float tx = rgbMat.width () - faceMaskMat.width () * scale;
float ty = 0.0f;
Mat trans = new Mat (2, 3, CvType.CV_32F);//1.0, 0.0, tx, 0.0, 1.0, ty);
trans.put (0, 0, scale);
trans.put (0, 1, 0.0f);
trans.put (0, 2, tx);
trans.put (1, 0, 0.0f);
trans.put (1, 1, scale);
trans.put (1, 2, ty);
Imgproc.warpAffine (faceMaskMat, rgbMat, trans, rgbMat.size (), Imgproc.INTER_LINEAR, Core.BORDER_TRANSPARENT, new Scalar (0));
}
Imgproc.putText (rgbMat, "W:" + rgbMat.width () + " H:" + rgbMat.height () + " SO:" + Screen.orientation, new Point (5, rgbMat.rows () - 10), Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar (255, 255, 255), 1, Imgproc.LINE_AA, false);
OpenCVForUnity.Utils.matToTexture2D (rgbMat, texture);
}
}
/// <summary>
/// Raises the disable event.
/// </summary>
void OnDestroy ()
{
WebGLFileUploadManager.FileUploadEventHandler -= fileUploadHandler;
WebGLFileUploadManager.Dispose ();
capture.release ();
if (rgbMat != null)
rgbMat.Dispose ();
if (grayMat != null)
grayMat.Dispose ();
if (rectangleTracker != null)
rectangleTracker.Dispose ();
if (faceLandmarkDetector != null)
faceLandmarkDetector.Dispose ();
if (frontalFaceParam != null)
frontalFaceParam.Dispose ();
}
/// <summary>
/// Raises the back button event.
/// </summary>
public void OnBackButton ()
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
SceneManager.LoadScene ("FaceMaskSample");
#else
Application.LoadLevel ("FaceMaskSample");
#endif
}
/// <summary>
/// Raises the is showing face rects toggle event.
/// </summary>
public void OnIsShowingFaceRectsToggle ()
{
if (isShowingFaceRectsToggle.isOn) {
isShowingFaceRects = true;
} else {
isShowingFaceRects = false;
}
}
/// <summary>
/// Raises the use Dlib face detector toggle event.
/// </summary>
public void OnUseDlibFaceDetecterToggle ()
{
if (useDlibFaceDetecterToggle.isOn) {
useDlibFaceDetecter = true;
} else {
useDlibFaceDetecter = false;
}
}
/// <summary>
/// Raises the is filtering non frontal faces toggle event.
/// </summary>
public void OnIsFilteringNonFrontalFacesToggle ()
{
if (isFilteringNonFrontalFacesToggle.isOn) {
isFilteringNonFrontalFaces = true;
} else {
isFilteringNonFrontalFaces = false;
}
}
/// <summary>
/// Raises the is showing debug face points toggle event.
/// </summary>
public void OnIsShowingDebugFacePointsToggle ()
{
if (isShowingDebugFacePointsToggle.isOn) {
isShowingDebugFacePoints = true;
} else {
isShowingDebugFacePoints = false;
}
}
/// <summary>
/// Raises the set face mask button event.
/// </summary>
public void OnChangeFaceMaskButton ()
{
removeFaceMask ();
SampleMaskData maskData = SampleDataSet.GetData();
faceMaskTexture = Resources.Load (maskData.FileName) as Texture2D;
faceMaskMat = new Mat (faceMaskTexture.height, faceMaskTexture.width, CvType.CV_8UC3);
OpenCVForUnity.Utils.texture2DToMat (faceMaskTexture, faceMaskMat);
Debug.Log ("faceMaskMat ToString " + faceMaskMat.ToString ());
if(maskData.LandmarkPoints != null){
faceRectInMask = maskData.FaceRect;
faceLandmarkPointsInMask = maskData.LandmarkPoints;
}else{
faceRectInMask = detectFace (faceMaskMat);
faceLandmarkPointsInMask = detectFaceLandmarkPoints (faceMaskMat, faceRectInMask);
}
SampleDataSet.Next();
if (faceRectInMask.width == 0 && faceRectInMask.height == 0){
removeFaceMask ();
Debug.Log ("A face could not be detected from the input image.");
}
}
/// <summary>
/// Raises the upload face mask button event.
/// </summary>
public void OnUploadFaceMaskButton ()
{
WebGLFileUploadManager.PopupDialog (null, "Select frontal face image file (.png|.jpg|.gif)");
}
/// <summary>
/// Raises the remove face mask button event.
/// </summary>
public void OnRemoveFaceMaskButton ()
{
removeFaceMask ();
}
private void removeFaceMask ()
{
faceMaskTexture = null;
if (faceMaskMat != null) {
faceMaskMat.Dispose ();
faceMaskMat = null;
}
rectangleTracker.Reset ();
meshOverlay.Reset ();
}
/// <summary>
/// Files the upload handler.
/// </summary>
/// <param name="result">Result.</param>
private void fileUploadHandler (UploadedFileInfo[] result)
{
if (result.Length == 0) {
Debug.Log ("File upload Error!");
return;
}
removeFaceMask ();
foreach (UploadedFileInfo file in result) {
if (file.isSuccess) {
Debug.Log ("file.filePath: " + file.filePath + " exists:" + File.Exists (file.filePath));
faceMaskTexture = new Texture2D (2, 2);
byte[] byteArray = File.ReadAllBytes (file.filePath);
faceMaskTexture.LoadImage (byteArray);
break;
}
}
if (faceMaskTexture != null) {
faceMaskMat = new Mat (faceMaskTexture.height, faceMaskTexture.width, CvType.CV_8UC3);
OpenCVForUnity.Utils.texture2DToMat (faceMaskTexture, faceMaskMat);
Debug.Log ("faceMaskMat ToString " + faceMaskMat.ToString ());
faceRectInMask = detectFace (faceMaskMat);
faceLandmarkPointsInMask = detectFaceLandmarkPoints (faceMaskMat, faceRectInMask);
if (faceRectInMask.width == 0 && faceRectInMask.height == 0){
removeFaceMask ();
Debug.Log ("A face could not be detected from the input image.");
}
}
}
private UnityEngine.Rect detectFace (Mat mat)
{
if (useDlibFaceDetecter) {
OpenCVForUnityUtils.SetImage (faceLandmarkDetector, mat);
List<UnityEngine.Rect> result = faceLandmarkDetector.Detect ();
if (result.Count >= 1)
return result [0];
} else {
using (Mat grayMat = new Mat ())
using (Mat equalizeHistMat = new Mat ())
using (MatOfRect faces = new MatOfRect ()) {
// convert image to greyscale.
Imgproc.cvtColor (mat, grayMat, Imgproc.COLOR_RGB2GRAY);
Imgproc.equalizeHist (grayMat, equalizeHistMat);
cascade.detectMultiScale (equalizeHistMat, faces, 1.1f, 2, 0 | Objdetect.CASCADE_SCALE_IMAGE, new OpenCVForUnity.Size (equalizeHistMat.cols () * 0.15, equalizeHistMat.cols () * 0.15), new Size ());
List<OpenCVForUnity.Rect> faceList = faces.toList ();
if (faceList.Count >= 1) {
UnityEngine.Rect r = new UnityEngine.Rect (faceList [0].x, faceList [0].y, faceList [0].width, faceList [0].height);
// Adjust to Dilb's result.
r.y += (int)(r.height * 0.1f);
return r;
}
}
}
return new UnityEngine.Rect ();
}
private List<Vector2> detectFaceLandmarkPoints (Mat mat, UnityEngine.Rect rect)
{
OpenCVForUnityUtils.SetImage (faceLandmarkDetector, mat);
List<Vector2> points = faceLandmarkDetector.DetectLandmark (rect);
return points;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a5cd7c2c97f800a46842b9454eb9f2f9
timeCreated: 1481920838
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 32541e47a39a06242ab093e9b213e99e
timeCreated: 1481920838
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

26
README.md Normal file
Просмотреть файл

@ -0,0 +1,26 @@
FaceMask Sample
====================
Overview
-----
<https://www.assetstore.unity3d.com/#!/content/79999>
Demo Video
-----
[![](http://img.youtube.com/vi/YNBz31vx15U/0.jpg)](https://www.youtube.com/watch?v=YNBz31vx15U)
Demo
-----
- WebGL
<https://enoxsoftware.github.io/FaceMaskSample/webgl_sample/index.html>
- WebGL(using shape_predictor_68_face_landmarks_for_mobile.dat)
<https://enoxsoftware.github.io/FaceMaskSample/webgl_sample_for_mobile/index.html>
- Android
<https://play.google.com/store/apps/details?id=com.enoxsoftware.facemasksample>
Manual
-----
[ReadMe.pdf](/FaceMaskSample/ReadMe.pdf)

7
StreamingAssets.meta Normal file
Просмотреть файл

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 058ff8aa85554aa4cbe51a95c5ed9ccb
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
StreamingAssets/dance.avi Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5b15518ef2238443905fff4839cfaec
timeCreated: 1483051440
licenseType: Free
MovieImporter:
serializedVersion: 1
quality: .5
linearTexture: 0
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e5e282d2065baf7408f080371d55511f
timeCreated: 1468559965
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

Двоичные данные
StreamingAssets/shape_predictor_68_face_landmarks.dat Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8104e65283de4d544acdad30db854ad2
timeCreated: 1467795760
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
WebGLFileUploader.meta Normal file
Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f2131656efcef9a42af1c7ab2dcaf829
folderAsset: yes
timeCreated: 1478281627
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6786a1b68a0f46c47b9d4dbdea15e3ac
folderAsset: yes
timeCreated: 1478290721
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: c552ab2acc359714380f21e2d83dc27e
folderAsset: yes
timeCreated: 1478290740
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,977 @@
var LibraryFileUploadManager = {
$Unity_FileUploadManager: {
detectOS:function(ua) {
switch (true) {
case /Android/.test(ua): return "Android";
case /iPhone|iPad|iPod/.test(ua): return "iOS";
case /Windows/.test(ua): return "Windows";
case /Mac OS X/.test(ua): return "Mac";
case /CrOS/.test(ua): return "Chrome OS";
case /Firefox/.test(ua): return "Firefox OS";
}
return "";
},
resample_hermite:function (img, W, H, W2, H2){
var canvas = document.createElement('canvas');
canvas.width = W2;
canvas.height = H2;
var ctx = canvas.getContext('2d');
var img2 = ctx.createImageData(W2, H2);
var data = img.data;
var data2 = img2.data;
var ratio_w = W / W2;
var ratio_h = H / H2;
var ratio_w_half = Math.ceil(ratio_w/2);
var ratio_h_half = Math.ceil(ratio_h/2);
for(var j = 0; j < H2; j++){
for(var i = 0; i < W2; i++){
var x2 = (i + j*W2) * 4;
var weight = 0;
var weights = 0;
var gx_r = 0, gx_g = 0, gx_b = 0, gx_a = 0;
var center_y = (j + 0.5) * ratio_h;
for(var yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++){
var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;
var center_x = (i + 0.5) * ratio_w;
var w0 = dy*dy;
for(var xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++){
var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;
var w = Math.sqrt(w0 + dx*dx);
if(w >= -1 && w <= 1){
weight = 2 * w*w*w - 3*w*w + 1;
if(weight > 0){
dx = 4*(xx + yy*W);
gx_r += weight * data[dx];
gx_g += weight * data[dx + 1];
gx_b += weight * data[dx + 2];
gx_a += weight * data[dx + 3];
weights += weight;
}
}
}
}
data2[x2] = gx_r / weights;
data2[x2 + 1] = gx_g / weights;
data2[x2 + 2] = gx_b / weights;
data2[x2 + 3] = gx_a / weights;
}
}
ctx.putImageData(img2, 0, 0);
return canvas;
},
getOrientation:function (imgDataURL){
var byteString = atob(imgDataURL.split(',')[1]);
var orientaion = byteStringToOrientation(byteString);
return orientaion;
function byteStringToOrientation(img){
var head = 0;
var orientation;
while (1){
if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 218) {break;}
if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 216) {
head += 2;
}
else {
var length = img.charCodeAt(head + 2) * 256 + img.charCodeAt(head + 3);
var endPoint = head + length + 2;
if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 225) {
var segment = img.slice(head, endPoint);
var bigEndian = segment.charCodeAt(10) == 77;
if (bigEndian) {
var count = segment.charCodeAt(18) * 256 + segment.charCodeAt(19);
} else {
var count = segment.charCodeAt(18) + segment.charCodeAt(19) * 256;
}
for (var i=0;i<count;i++){
var field = segment.slice(20 + 12 * i, 32 + 12 * i);
if ((bigEndian && field.charCodeAt(1) == 18) || (!bigEndian && field.charCodeAt(0) == 18)) {
orientation = bigEndian ? field.charCodeAt(9) : field.charCodeAt(8);
}
}
break;
}
head = endPoint;
}
if (head > img.length){break;}
}
return orientation;
}
},
detectSubsampling:function (img) {
var iw = img.naturalWidth, ih = img.naturalHeight;
if (iw * ih > 1024 * 1024) {
var canvas = document.createElement('canvas');
canvas.width = canvas.height = 1;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, -iw + 1, 0);
return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
} else {
return false;
}
},
detectVerticalSquash:function (img, iw, ih) {
var canvas = document.createElement('canvas');
canvas.width = 1;
canvas.height = ih;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
var data = ctx.getImageData(0, 0, 1, ih).data;
var sy = 0;
var ey = ih;
var py = ih;
while (py > sy) {
var alpha = data[(py - 1) * 4 + 3];
if (alpha === 0) {
ey = py;
} else {
sy = py;
}
py = (ey + sy) >> 1;
}
var ratio = (py / ih);
return (ratio===0)?1:ratio;
},
transformCoordinate:function (canvas, width, height, orientation) {
if (orientation > 4) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
var ctx = canvas.getContext('2d');
switch (orientation) {
case 2:
// horizontal flip
ctx.translate(width, 0);
ctx.scale(-1, 1);
break;
case 3:
// 180 rotate left
ctx.translate(width, height);
ctx.rotate(Math.PI);
break;
case 4:
// vertical flip
ctx.translate(0, height);
ctx.scale(1, -1);
break;
case 5:
// vertical flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.scale(1, -1);
break;
case 6:
// 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.translate(0, -height);
break;
case 7:
// horizontal flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.translate(width, -height);
ctx.scale(-1, 1);
break;
case 8:
// 90 rotate left
ctx.rotate(-0.5 * Math.PI);
ctx.translate(-width, 0);
break;
default:
break;
}
},
dataURLtoArrayBuffer:function (dataurl) {
var bin = atob(dataurl.split("base64,")[1]);
var len = bin.length;
var barr = new Uint8Array(len);
for (var i = 0; i < len; i++) {
barr[i] = bin.charCodeAt(i);
}
return barr.buffer;
},
isInitialized:false,
isDebug:false,
isDropInput:false,
isOverlay:false,
isPopupDialog:false,
enableImageEncoding:true,
imageEncodingThreshold:0,
imageShrinkingSizeWidth:640,
imageShrinkingSizeHeight:480,
jsCallCsCallback:null,
filenameRegStr:".*",
descriptionStr:null,
popupDialogCompleteFunc:null,
ERROR_CODE:{
NONE : 0,
NOT_FOUND_ERR : 1,
SECURITY_ERR : 2,
ABORT_ERR : 3,
NOT_READABLE_ERRF : 4,
ENCODING_ERR : 5,
IMG_LOAD_ERR : 6,
FS_IO_ERR : 7,
NOT_ALLOWED_FILENAME : 8,
},
checkExistAPI:function() {
return (!window.File || !window.FileReader || !window.Promise) ? false : true;
},
createRequiredHTML:function() {
var fileUploaderElem = document.getElementById('file_uploader');
if(fileUploaderElem == null){
var canvas = document.getElementById('canvas');
var fileUploaderElem = document.createElement('div');
fileUploaderElem.id = 'file_uploader';
canvas.parentNode.insertBefore(fileUploaderElem, canvas.nextSibling);
}
var fileListElem = document.getElementById('file_uploader_file_list');
if(fileListElem == null){
var fileUploaderElem = document.getElementById('file_uploader');
var fileListElem = document.createElement('div');
fileListElem.id = 'file_uploader_file_list';
fileUploaderElem.parentNode.insertBefore(fileListElem, fileUploaderElem.nextSibling);
}
},
handleFileSelect:function (evt) {
var files; // FileList object.
if(Unity_FileUploadManager.isDropInput){
evt.stopPropagation();
evt.preventDefault();
files = evt.dataTransfer.files;
document.getElementById('file_drop_area').classList.remove('onDragOver');
}else{
files = evt.target.files;
}
document.getElementById('file_uploader_file_list').innerHTML = '';
var dirpathStr = "fileuploader";
var filenameReg = new RegExp(Unity_FileUploadManager.filenameRegStr, 'i');
var imageFileTypeReg = new RegExp("image\/(png|jpeg|gif)$", 'i');
// create data directory.
try {
var stat = FS.stat('/' + dirpathStr);
} catch (e) {
FS.mkdir('/' + dirpathStr);
}
function readImageFile(result) {
return new Promise(function(resolve, reject) {
//if(Unity_FileUploadManager.isDebug) console.log("readImageFile: " + result.file.name);
var maxWidth = Unity_FileUploadManager.imageShrinkingSizeWidth;
var maxHeight = Unity_FileUploadManager.imageShrinkingSizeHeight;
var file = result.file;
if (!file.type.match(/^image\/(png|jpeg|gif)$/)) return;
var img = new Image();
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
img.onload = function() {
var iw = img.naturalWidth, ih = img.naturalHeight;
var width = iw, height = ih;
var orientation;
// In the case of JPEG, obtain Orientation (rotation) information from EXIF.
if (data.split(',')[0].match('jpeg')) {
orientation = Unity_FileUploadManager.getOrientation(data);
}
// If it is not JPEG or EXIF is not JPEG, set it to the standard value.
orientation = orientation || 1;
// For example, rotate 90 degrees, if the aspect ratio changes, change the maximum width and height beforehand.
if (orientation > 4) {
var tmpMaxWidth = maxWidth;
maxWidth = maxHeight;
maxHeight = tmpMaxWidth;
}
if(width > maxWidth || height > maxHeight) {
var ratio = width/maxWidth;
if(ratio <= height/maxHeight) {
ratio = height/maxHeight;
}
width = Math.floor(img.width/ratio);
height = Math.floor(img.height/ratio);
}
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.save();
// Rotate Canvas from EXIF's Orientation information.
Unity_FileUploadManager.transformCoordinate(canvas, width, height, orientation);
// Avoid iPhone subsampling problems.
var subsampled = Unity_FileUploadManager.detectSubsampling(img);
if (subsampled) {
iw /= 2;
ih /= 2;
}
var d = 1024; // size of tiling canvas
var tmpCanvas = document.createElement('canvas');
tmpCanvas.width = tmpCanvas.height = d;
var tmpCtx = tmpCanvas.getContext('2d');
var vertSquashRatio = Unity_FileUploadManager.detectVerticalSquash(img, iw, ih);
var dw = Math.ceil(d * width / iw);
var dh = Math.ceil(d * height / ih / vertSquashRatio);
var sy = 0;
var dy = 0;
while (sy < ih) {
var sx = 0;
var dx = 0;
while (sx < iw) {
tmpCtx.clearRect(0, 0, d, d);
tmpCtx.drawImage(img, -sx, -sy);
var imageData = tmpCtx.getImageData(0, 0, d, d);
var resampled = Unity_FileUploadManager.resample_hermite(imageData, d, d, dw, dh);
ctx.drawImage(resampled, 0, 0, dw, dh, dx, dy, dw, dh);
sx += d;
dx += dw;
}
sy += d;
dy += dh;
}
ctx.restore();
tmpCanvas = tmpCtx = null;
//display new Image.
var displaySrc = ctx.canvas.toDataURL('image/jpeg', .9);
/*
var displayImg = document.createElement('img');
displayImg.id = 'preview';
displayImg.setAttribute('src', displaySrc);
displayImg.setAttribute('alt', file.name);
displayImg.setAttribute('style','max-width:90%;max-height:90%');
document.getElementById('file_uploader_file_list').appendChild(displayImg);
*/
// dataURL to ArrayBuffer.
result.buf = Unity_FileUploadManager.dataURLtoArrayBuffer(displaySrc);
result.name = result.file.name.match(/(.*)(?:\.([^.]+$))/)[1] + ".jpg";
result.size = result.buf.byteLength;
result.type = "image/jpeg";
resolve(writeFileToFS(result));
}
img.onerror = function () {
result.errorCode = Unity_FileUploadManager.ERROR_CODE.IMG_LOAD_ERR;
resolve(result);
}
img.src = data;
}
reader.onerror = function (event) {
result.errorCode = reader.error.code;//Unity_FileUploadManager.ERROR_CODE15
resolve(result);
}
reader.readAsDataURL(file);
});
}
function readBinaryFile(result) {
return new Promise(function(resolve, reject) {
//if(Unity_FileUploadManager.isDebug) console.log("readBinaryFile: " + result.file.name);
var reader = new FileReader();
reader.onload = function (event) {
result.buf = reader.result;
resolve(writeFileToFS(result));
}
reader.onerror = function (event) {
result.errorCode = reader.error.code;//Unity_FileUploadManager.ERROR_CODE15
resolve(result);
}
reader.readAsArrayBuffer(result.file);
});
}
function writeFileToFS(result) {
return new Promise(function(resolve, reject) {
//if(Unity_FileUploadManager.isDebug) console.log("writeFileToFS: " + result.name);
try {
var filePath = '/' + dirpathStr + '/' + escape(result.name);
var u8Arr = new Uint8Array(result.buf);
var stream = FS.open(filePath, 'w+');
FS.write(stream, u8Arr, 0, u8Arr.length, 0);
FS.close(stream);
delete result.buf;
delete u8arr;
//debug
//var stat = FS.stat(filePath);
//console.log(stat);
//
result.filePath = filePath;
result.isSuccess = true;
resolve(result);
} catch (e) {
//if(Unity_FileUploadManager.isDebug) console.log("writeFileToFS: " + result.name + " " + e);
result.errorCode = Unity_FileUploadManager.ERROR_CODE.FS_IO_ERR;
resolve(result);
}
});
}
function callbackCS(results) {
var returnStr;
if(results != null){
var destFileArray = [];
var len = results.length;
for (var i=0; i<len; i++){
var result = results[i];
var file = result.file;
var o = {"name":result.name, "type":result.type, "size":result.size, "lastModified":file.lastModified, "filePath":result.filePath, "isSuccess":result.isSuccess, "errorCode":result.errorCode};
destFileArray.push(o);
}
var object = {"files":destFileArray};
var fileUploadDataJSON = JSON.stringify(object);
returnStr = fileUploadDataJSON;
}else{
returnStr = "";
}
var buffer = _malloc(lengthBytesUTF8(returnStr) + 1);
writeStringToMemory(returnStr, buffer);
Runtime.dynCall('vi', Unity_FileUploadManager.jsCallCsCallback, [buffer]);
_free(buffer);
}
_Unity_FileUploadManager_Disable();
var results = [];
for (var i = 0, f; f = files[i]; i++) {
results.push({"file":f, "name":f.name, "size":f.size, "type":f.type, "buf":null, "filePath":"", "isSuccess":false, "errorCode":Unity_FileUploadManager.ERROR_CODE.NONE});
}
Promise.resolve()
.then(function(){
return Promise.all(results.map(function(result){
return new Promise(function(resolve, reject){
//Allowed file name?
if(filenameReg.test(result.file.name)){
//Image File?
if(Unity_FileUploadManager.enableImageEncoding && Unity_FileUploadManager.imageEncodingThreshold <= result.file.size && imageFileTypeReg.test(result.file.type)){
resolve(readImageFile(result));
}else{
resolve(readBinaryFile(result));
}
}else{
result.errorCode = Unity_FileUploadManager.ERROR_CODE.NOT_ALLOWED_FILENAME;
resolve(result);
}
})
}))
})
.then(function(results){
if(Unity_FileUploadManager.isDebug) Unity_FileUploadManager.outputFileList(results);
callbackCS(results);
_Unity_FileUploadManager_Enable();
if(Unity_FileUploadManager.popupDialogCompleteFunc != null) Unity_FileUploadManager.popupDialogCompleteFunc();
})
.catch(function(err) {
console.log(err);
callbackCS(null);
_Unity_FileUploadManager_Enable();
if(Unity_FileUploadManager.popupDialogCompleteFunc != null) Unity_FileUploadManager.popupDialogCompleteFunc();
});
},
handleDragOver:function (evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
document.getElementById('file_drop_area').classList.add('onDragOver');
},
handleDragEnter:function (evt) {
evt.stopPropagation();
evt.preventDefault();
},
handleDragLeave:function (evt) {
evt.stopPropagation();
evt.preventDefault();
document.getElementById('file_drop_area').classList.remove('onDragOver');
},
outputFileList: function (results) {
var output = [];
var len = results.length;
for (var i=0; i<len; i++){
var result = results[i];
var f = result.file;
output.push('<li' , (result.isSuccess)?'':' style="color: #bbb"' , '>', escape(result.name), ' (', result.type || 'n/a', ') - ',
result.size, ' bytes, last modified: ',
f.lastModified, (result.isSuccess) ? ' filePath=' : ' errorCode=', (result.isSuccess) ? result.filePath : result.errorCode,'</li>');
console.log("result" + i + ": " + f.name + " " + f.size + " " + f.type + " " + f.lastModified + " / " + result.name + " " + result.size + " " + result.type + " " + result.isSuccess + " " + result.filePath + " " + result.errorCode);
}
document.getElementById('file_uploader_file_list').innerHTML += "<ul>" + output.join('') + "</ul>";
}
},
Unity_FileUploadManager_IsInitialized: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_IsInitialized()");
return Unity_FileUploadManager.isInitialized;
},
Unity_FileUploadManager_InitFileUploader: function(isDropInput, isOverlay)
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_InitFileUploader()");
Unity_FileUploadManager.isDropInput = isDropInput;
Unity_FileUploadManager.isOverlay = isOverlay;
if(!Unity_FileUploadManager.checkExistAPI()) {
console.log("Does not exist API necessary.");
return false;
}
Unity_FileUploadManager.createRequiredHTML();
var fileUploaderElem = document.getElementById('file_uploader');
var fileListElem = document.getElementById('file_uploader_file_list');
if(Unity_FileUploadManager.isDropInput){
Unity_FileUploadManager.descriptionStr = "Drop files here";
fileUploaderElem.innerHTML = '<div id="file_drop_area">' + Unity_FileUploadManager.descriptionStr + '</div>';
var dropAreaElem = document.getElementById('file_drop_area');
// Setup the dnd listeners.
dropAreaElem.addEventListener('dragover', Unity_FileUploadManager.handleDragOver, false);
dropAreaElem.addEventListener('drop', Unity_FileUploadManager.handleFileSelect, false);
dropAreaElem.addEventListener('dragenter', Unity_FileUploadManager.handleDragEnter, false);
dropAreaElem.addEventListener('dragleave', Unity_FileUploadManager.handleDragLeave, false);
fileUploaderElem.classList.add('isDropInput');
}else{
Unity_FileUploadManager.descriptionStr = "Select files";
var html = '<label for="file_input" id="file_input_button">' +
' <div id="file_input_description">' + Unity_FileUploadManager.descriptionStr + '</div>' +
' <input type="file" id="file_input" name="files[]" style="display:none;" multiple />' +
'</label>';
fileUploaderElem.innerHTML = html;
// Setup the input listeners.
document.getElementById('file_input').addEventListener('change', Unity_FileUploadManager.handleFileSelect, false);
fileUploaderElem.classList.add('isButtonInput');
}
fileUploaderElem.classList.remove('hidden');
fileListElem.innerHTML = '';
if(Unity_FileUploadManager.isDebug) {
fileListElem.classList.remove('hidden');
}else{
fileListElem.classList.add('hidden');
}
var canvasElem = document.getElementById('canvas');
if(isOverlay){
fileUploaderElem.style.setProperty("width", canvasElem.width + "px", "important");
fileUploaderElem.style.setProperty("height", canvasElem.height + "px", "important");
fileUploaderElem.classList.add('overlay_canvas');
if(Unity_FileUploadManager.isDropInput){
var dropAreaElem = document.getElementById('file_drop_area');
dropAreaElem.classList.add('overlay');
}else{
var inputButtonElem = document.getElementById('file_input_button');
inputButtonElem.classList.add('overlay');
}
}
Unity_FileUploadManager.isInitialized = true;
return Unity_FileUploadManager.isInitialized;
},
/*
Unity_FileUploadManager_InitUGUIButton: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_InitUGUIButton()");
Unity_FileUploadManager.isDropInput = false;
Unity_FileUploadManager.isOverlay = false;
var fileInputElem = document.getElementById('file_input');
var e = document.createEvent("MouseEvents");
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false,
false, false, false, 0, null);
fileInputElem.dispatchEvent(e);
return Unity_FileUploadManager.isInitialized;
},
*/
Unity_FileUploadManager_PopupDialog: function(titleText, uploadBtnText, cancelBtnText)
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_PopupDialog()");
titleText = Pointer_stringify(titleText);
uploadBtnText = Pointer_stringify(uploadBtnText);
cancelBtnText = Pointer_stringify(cancelBtnText);
Unity_FileUploadManager.isDropInput = false;
Unity_FileUploadManager.isPopupDialog = true;
if(!Unity_FileUploadManager.checkExistAPI()) {
console.log("Does not exist API necessary.");
return false;
}
Unity_FileUploadManager.createRequiredHTML();
Unity_FileUploadManager.descriptionStr = "Select files";
var html = ' <div id="popup_dialog">' +
' <div id="popup_dialog_title">Here is title</div>' +
' <div id="popup_dialog_file_input_button_warp">' +
' <label for="file_input" id="popup_dialog_file_input_button">' +
' <div id="file_input_description">Select files</div>' +
' <input type="file" id="file_input" name="files[]" style="display:none;" multiple />' +
' </label>' +
' </div>' +
' <div id="popup_dialog_cancel_button_warp">' +
' <input id="popup_dialog_cancel_button" type="button" value="Cancel">' +
' </div>' +
'</div>';
var popup_dialog_warpElem = document.getElementById('popup_dialog_warp');
if(popup_dialog_warpElem == null){
popup_dialog_warpElem = document.createElement('div');
popup_dialog_warpElem.id = 'popup_dialog_warp';
document.body.appendChild( popup_dialog_warpElem );
}
popup_dialog_warpElem.innerHTML = html;
popup_dialog_warpElem.style.display = "";
Unity_FileUploadManager.popupDialogCompleteFunc = function (){
document.getElementById("canvas").style.display="";
_Unity_FileUploadManager_Dispose();
};
// Setup the input listeners.
var fileInputElem = document.getElementById('file_input');
fileInputElem.addEventListener('change', (function(e) {
return function f(e) {
fileInputElem.removeEventListener('change', f, false);
document.getElementById("popup_dialog_file_input_button_warp").style.display = "none";
document.getElementById("popup_dialog_cancel_button_warp").style.display = "none";
document.getElementById("popup_dialog_title").innerHTML = 'Now Loading...';
Unity_FileUploadManager.handleFileSelect(e);
}
})(1), false);
var cancelBtn = document.getElementById("popup_dialog_cancel_button");
cancelBtn.addEventListener('click', (function(x) {
return function f() {
cancelBtn.removeEventListener('click', f, false);
Unity_FileUploadManager.popupDialogCompleteFunc();
}
})(1), false);
document.getElementById("popup_dialog_title").innerText = (titleText != '') ? titleText : 'File Uploader';
document.getElementById("file_input_description").innerText = (uploadBtnText != '') ? uploadBtnText : Unity_FileUploadManager.descriptionStr;
document.getElementById("popup_dialog_cancel_button").value = (cancelBtnText != '') ? cancelBtnText : 'Cancel';
Unity_FileUploadManager.isInitialized = true;
return Unity_FileUploadManager.isInitialized;
},
Unity_FileUploadManager_HideUnityScreenIfHtmlOverlayCant: function(){
if( navigator.userAgent.indexOf("Chrome/") < 0 ){
document.getElementById("canvas").style.display="none";
}
},
Unity_FileUploadManager_IsRunningOnEdgeBrowser: function(){
if( navigator.userAgent.indexOf("Edge/") < 0 ){
return false;
}
return true;
},
Unity_FileUploadManager_Dispose: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_Dispose()");
var fileUploaderElem = document.getElementById('file_uploader');
if(Unity_FileUploadManager.isOverlay){
fileUploaderElem.style.removeProperty("width");
fileUploaderElem.style.removeProperty("height");
fileUploaderElem.classList.remove('overlay_canvas');
}
if(Unity_FileUploadManager.isDropInput){
var dropAreaElem = document.getElementById('file_drop_area');
// Remove the dnd listeners.
dropAreaElem.removeEventListener('dragover', Unity_FileUploadManager.handleDragOver, false);
dropAreaElem.removeEventListener('drop', Unity_FileUploadManager.handleFileSelect, false);
dropAreaElem.removeEventListener('dragenter', Unity_FileUploadManager.handleDragEnter, false);
dropAreaElem.removeEventListener('dragleave', Unity_FileUploadManager.handleDragLeave, false);
fileUploaderElem.innerHTML = '';
fileUploaderElem.classList.remove('isDropInput');
}else{
// Remove the input listeners.
document.getElementById('file_input').removeEventListener('change', Unity_FileUploadManager.handleFileSelect, false);
fileUploaderElem.innerHTML = '';
fileUploaderElem.classList.remove('isButtonInput');
}
fileUploaderElem.classList.add('hidden');
var fileListElem = document.getElementById('file_uploader_file_list');
fileListElem.innerHTML = '';
fileListElem.classList.add('hidden');
if(Unity_FileUploadManager.isPopupDialog){
Unity_FileUploadManager.popupDialogCompleteFunc = null;
document.getElementById("popup_dialog_warp").style.display = "none";
document.getElementById('popup_dialog_warp').innerHTML = '';
}
Unity_FileUploadManager.jsCallCsCallback = null;
Unity_FileUploadManager.isInitialized = false;
Unity_FileUploadManager.isDropInput = false;
Unity_FileUploadManager.isOverlay = false;
Unity_FileUploadManager.isPopupDialog = false;
},
Unity_FileUploadManager_SetCallback: function(callback)
{
//console.log("Unity_FileUploadManager_SetCallback()");
Unity_FileUploadManager.jsCallCsCallback = callback;
},
Unity_FileUploadManager_IsDropInput: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_IsDropInput()");
return Unity_FileUploadManager.isDropInput;
},
Unity_FileUploadManager_IsOverlay: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_IsOverlay()");
return Unity_FileUploadManager.isOverlay;
},
Unity_FileUploadManager_IsPopupDialog: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_IsPopupDialog()");
return Unity_FileUploadManager.isPopupDialog;
},
Unity_FileUploadManager_SetDebug: function(value)
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_IsDebug()");
Unity_FileUploadManager.isDebug = value;
var fileListElem = document.getElementById('file_uploader_file_list');
if(fileListElem != null){
if(Unity_FileUploadManager.isDebug) {
fileListElem.classList.remove('hidden');
}else{
fileListElem.classList.add('hidden');
}
}
},
Unity_FileUploadManager_SetDescription: function(descriptionStr)
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_SetDescription()");
var descriptionStr = Pointer_stringify(descriptionStr);
if(Unity_FileUploadManager.isDropInput){
if(descriptionStr == "") descriptionStr = "Drop files here";
var fileDropArea = document.getElementById('file_drop_area');
if(fileDropArea) fileDropArea.textContent = descriptionStr;
}else{
if(descriptionStr == "") descriptionStr = "Select files";
var fileInputDescripton = document.getElementById('file_input_description');
if(fileInputDescripton) fileInputDescripton.innerHTML = descriptionStr;
}
Unity_FileUploadManager.descriptionStr = descriptionStr;
},
Unity_FileUploadManager_SetAllowedFileName: function(filenameRegStr)
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_SetAllowedFileName()");
var filenameRegStr = Pointer_stringify(filenameRegStr);
if(filenameRegStr == "") filenameRegStr = ".*";
Unity_FileUploadManager.filenameRegStr = filenameRegStr;
},
Unity_FileUploadManager_SetImageEncodeSetting: function(enable, threshold)
{
Unity_FileUploadManager.enableImageEncoding = enable;
if(threshold >= 0) Unity_FileUploadManager.imageEncodingThreshold = threshold;
},
Unity_FileUploadManager_SetImageShrinkingSize: function(width, height)
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_SetImageShrinkingSize()");
Unity_FileUploadManager.imageShrinkingSizeWidth = width>0 ? width : 1;
Unity_FileUploadManager.imageShrinkingSizeHeight = height>0 ? height : 1;
},
Unity_FileUploadManager_SetInputArea: function(x, y, width, height)
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_SetInputArea()");
if(Unity_FileUploadManager.isPopupDialog) return;
var targetElem;
if(Unity_FileUploadManager.isDropInput){
targetElem = document.getElementById('file_drop_area');
}else{
targetElem = document.getElementById('file_input_button');
}
if(x < 0 || y < 0 || width < 0 || height < 0){
targetElem.style.top = '';
targetElem.style.left = '';
targetElem.style.width = '';
targetElem.style.height = '';
targetElem.style.lineHeight = '';
}else{
targetElem.style.top = x + 'px';
targetElem.style.left = y + 'px';
targetElem.style.width = width + 'px';
targetElem.style.height = height + 'px';
targetElem.style.lineHeight = height + 'px';
}
},
Unity_FileUploadManager_Show: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_Show()");
var fileUploaderElem = document.getElementById('file_uploader');
fileUploaderElem.classList.remove('hidden');
var fileListElem = document.getElementById('file_uploader_file_list');
if(Unity_FileUploadManager.isDebug) fileListElem.classList.remove('hidden');
},
Unity_FileUploadManager_Hide: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_Hide()");
var fileUploaderElem = document.getElementById('file_uploader');
fileUploaderElem.classList.add('hidden');
var fileListElem = document.getElementById('file_uploader_file_list');
fileListElem.classList.add('hidden');
},
Unity_FileUploadManager_Enable: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_Enable()");
if(Unity_FileUploadManager.isDropInput){
var fileDropArea = document.getElementById('file_drop_area');
if(fileDropArea) fileDropArea.classList.remove('disable');
}else{
var fileInputButton = document.getElementById('file_input_button');
if(fileInputButton) fileInputButton.classList.remove('disable');
}
},
Unity_FileUploadManager_Disable: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_Disable()");
if(Unity_FileUploadManager.isDropInput){
var fileDropArea = document.getElementById('file_drop_area');
if(fileDropArea) fileDropArea.classList.add('disable');
}else{
var fileInputButton = document.getElementById('file_input_button');
if(fileInputButton) fileInputButton.classList.add('disable');
}
},
Unity_FileUploadManager_Click: function()
{
if(Unity_FileUploadManager.isDebug) console.log("Unity_FileUploadManager_Click()");
if(!Unity_FileUploadManager.isDropInput){
var fileInputElem = document.getElementById('file_input');
console.log(fileInputElem);
var e = document.createEvent("MouseEvents");
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false,
false, false, false, 0, null);
fileInputElem.dispatchEvent(e);
}
var foobarElem = document.getElementById('foobar');
var e = document.createEvent("MouseEvents");
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false,
false, false, false, 0, null);
foobarElem.dispatchEvent(e);
},
Unity_FileUploadManager_GetOS: function()
{
var returnStr = Unity_FileUploadManager.detectOS(navigator.userAgent);
var buffer = _malloc(lengthBytesUTF8(returnStr) + 1);
writeStringToMemory(returnStr, buffer);
return buffer;
},
Unity_FileUploadManager_IsMobile: function()
{
var ua = navigator.userAgent;
var os = Unity_FileUploadManager.detectOS(ua);
return (/Android|iOS/.test(os) || /Windows Phone/.test(ua));
},
Unity_FileUploadManager_GetUserAgent: function()
{
var returnStr = navigator.userAgent;
var buffer = _malloc(lengthBytesUTF8(returnStr) + 1);
writeStringToMemory(returnStr, buffer);
return buffer;
}
};
autoAddDeps(LibraryFileUploadManager, '$Unity_FileUploadManager');
autoAddDeps(LibraryFileUploadManager, 'Unity_FileUploadManager_Dispose');
autoAddDeps(LibraryFileUploadManager, 'Unity_FileUploadManager_Enable');
autoAddDeps(LibraryFileUploadManager, 'Unity_FileUploadManager_Disable');
mergeInto(LibraryManager.library, LibraryFileUploadManager);

Просмотреть файл

@ -0,0 +1,49 @@
fileFormatVersion: 2
guid: 8067a755102339c4a894c0498d066b8f
timeCreated: 1478295301
licenseType: Free
PluginImporter:
serializedVersion: 1
iconMap: {}
executionOrder: {}
isPreloaded: 0
platformData:
Any:
enabled: 0
settings: {}
Editor:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux:
enabled: 0
settings:
CPU: x86
Linux64:
enabled: 0
settings:
CPU: x86_64
OSXIntel:
enabled: 0
settings:
CPU: AnyCPU
OSXIntel64:
enabled: 0
settings:
CPU: AnyCPU
WebGL:
enabled: 1
settings: {}
Win:
enabled: 0
settings:
CPU: AnyCPU
Win64:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ff9a23be45dc9bd46b5beb6fbcd1ca8c
folderAsset: yes
timeCreated: 1478290818
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ad142859d38701141b769da33e91b16b
folderAsset: yes
timeCreated: 1478445263
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,108 @@
using System.Collections;
using System.IO;
using UnityEngine;
using WebGLFileUploader;
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
using UnityEngine.SceneManagement;
#endif
namespace WebGLFileUploaderSample
{
/// <summary>
/// File Upload sample.
/// </summary>
public class FileUploadSample : MonoBehaviour
{
// Use this for initialization
void Start ()
{
Debug.Log("WebGLFileUploadManager.getOS: " + WebGLFileUploadManager.getOS);
Debug.Log("WebGLFileUploadManager.isMOBILE: " + WebGLFileUploadManager.IsMOBILE);
Debug.Log("WebGLFileUploadManager.getUserAgent: " + WebGLFileUploadManager.GetUserAgent);
WebGLFileUploadManager.SetDebug(true);
if (
#if UNITY_WEBGL && !UNITY_EDITOR
WebGLFileUploadManager.IsMOBILE
#else
Application.isMobilePlatform
#endif
) {
if(!WebGLFileUploadManager.IsInitialized) WebGLFileUploadManager.InitFileUploader (false);
WebGLFileUploadManager.SetDescription("Select image files (.png|.jpg|.gif)");
}else{
if(!WebGLFileUploadManager.IsInitialized) WebGLFileUploadManager.InitFileUploader (true);
WebGLFileUploadManager.SetDescription("Drop image files (.png|.jpg|.gif) here");
}
WebGLFileUploadManager.SetImageEncodeSetting(true);
WebGLFileUploadManager.SetAllowedFileName("\\.(png|jpe?g|gif)$");
WebGLFileUploadManager.SetImageShrinkingSize(1280 ,960);
WebGLFileUploadManager.FileUploadEventHandler += fileUploadHandler;
}
// Update is called once per frame
void Update ()
{
}
void OnDestroy ()
{
WebGLFileUploadManager.FileUploadEventHandler -= fileUploadHandler;
WebGLFileUploadManager.Dispose();
}
private void fileUploadHandler(UploadedFileInfo[] result){
if(result.Length == 0) {
Debug.Log("File upload Error!");
}else{
Debug.Log("File upload success! (result.Length: " + result.Length + ")");
}
foreach(UploadedFileInfo file in result){
if(file.isSuccess){
Debug.Log("file.filePath: " + file.filePath + " exists:" + File.Exists(file.filePath));
Texture2D texture = new Texture2D (2, 2);
byte[] byteArray = File.ReadAllBytes (file.filePath);
texture.LoadImage (byteArray);
gameObject.GetComponent<Renderer> ().material.mainTexture = texture;
Debug.Log("File.ReadAllBytes:byte[].Length: " + byteArray.Length);
break;
}
}
}
public void OnBackButton ()
{
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
SceneManager.LoadScene ("WebGLFileUploaderSample");
#else
Application.LoadLevel ("WebGLFileUploaderSample");
#endif
}
public void OnButtonOverlayToggleButton ()
{
WebGLFileUploadManager.InitFileUploader(false, !WebGLFileUploadManager.IsOverlay);
}
public void OnDropOverlayToggleButton ()
{
WebGLFileUploadManager.InitFileUploader(true, !WebGLFileUploadManager.IsOverlay);
}
public void OnPopupDialogButton ()
{
WebGLFileUploadManager.PopupDialog(null, "Select image files (.png|.jpg|.gif)");
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 74c8910a0e9ba4246b45db5c8e0600cc
timeCreated: 1478290954
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,6 @@
fileFormatVersion: 2
guid: 994ec4107af5eac48b07baa79707593e
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше