123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854 |
- using UnityEngine;
- using UnityEngine.SceneManagement;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Threading;
- using OpenCVForUnity.CoreModule;
- using OpenCVForUnity.ObjdetectModule;
- using OpenCVForUnity.ImgprocModule;
- using OpenCVForUnity.UnityUtils;
- using OpenCVForUnity.UnityUtils.Helper;
- using Rect = OpenCVForUnity.CoreModule.Rect;
- using PositionsVector = System.Collections.Generic.List<OpenCVForUnity.CoreModule.Rect>;
- namespace OpenCVForUnityExample
- {
- /// <summary>
- /// Asynchronous Face Detection WebCamTexture Example
- /// Referring to https://github.com/Itseez/opencv/blob/master/modules/objdetect/src/detection_based_tracker.cpp.
- /// </summary>
- [RequireComponent (typeof(WebCamTextureToMatHelper))]
- public class AsynchronousFaceDetectionWebCamTextureExample : MonoBehaviour
- {
- /// <summary>
- /// The gray mat.
- /// </summary>
- Mat grayMat;
- /// <summary>
- /// The texture.
- /// </summary>
- Texture2D texture;
- /// <summary>
- /// The webcam texture to mat helper.
- /// </summary>
- WebCamTextureToMatHelper webCamTextureToMatHelper;
- /// <summary>
- /// The cascade.
- /// </summary>
- CascadeClassifier cascade;
- /// <summary>
- /// The lbpcascade_frontalface_xml_filepath.
- /// </summary>
- string lbpcascade_frontalface_xml_filepath;
-
- /// <summary>
- /// The haarcascade_frontalface_alt_xml_filepath.
- /// </summary>
- string haarcascade_frontalface_alt_xml_filepath;
- /// <summary>
- /// The rects where regions.
- /// </summary>
- Rect[] rectsWhereRegions;
- /// <summary>
- /// The detected objects in regions.
- /// </summary>
- List<Rect> detectedObjectsInRegions = new List<Rect> ();
- /// <summary>
- /// The result objects.
- /// </summary>
- List<Rect> resultObjects = new List<Rect> ();
- // for Thread
- CascadeClassifier cascade4Thread;
- Mat grayMat4Thread;
- MatOfRect detectionResult;
- System.Object sync = new System.Object ();
- bool _isThreadRunning = false;
- bool isThreadRunning {
- get {
- lock (sync)
- return _isThreadRunning;
- }
- set {
- lock (sync)
- _isThreadRunning = value;
- }
- }
- bool _shouldStopThread = false;
- bool shouldStopThread {
- get {
- lock (sync)
- return _shouldStopThread;
- }
- set {
- lock (sync)
- _shouldStopThread = value;
- }
- }
- bool _shouldDetectInMultiThread = false;
- bool shouldDetectInMultiThread {
- get {
- lock (sync)
- return _shouldDetectInMultiThread;
- }
- set {
- lock (sync)
- _shouldDetectInMultiThread = value;
- }
- }
- bool _didUpdateTheDetectionResult = false;
- bool didUpdateTheDetectionResult {
- get {
- lock (sync)
- return _didUpdateTheDetectionResult;
- }
- set {
- lock (sync)
- _didUpdateTheDetectionResult = value;
- }
- }
- /// <summary>
- /// The FPS monitor.
- /// </summary>
- FpsMonitor fpsMonitor;
- // for tracker
- List<TrackedObject> trackedObjects = new List<TrackedObject> ();
- List<float> weightsPositionsSmoothing = new List<float> ();
- List<float> weightsSizesSmoothing = new List<float> ();
- Parameters parameters;
- InnerParameters innerParameters;
- #if UNITY_WEBGL && !UNITY_EDITOR
- IEnumerator getFilePath_Coroutine;
- #endif
- // Use this for initialization
- void Start ()
- {
- fpsMonitor = GetComponent<FpsMonitor> ();
- webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper> ();
- #if UNITY_WEBGL && !UNITY_EDITOR
- getFilePath_Coroutine = GetFilePath ();
- StartCoroutine (getFilePath_Coroutine);
- #else
- lbpcascade_frontalface_xml_filepath = Utils.getFilePath ("lbpcascade_frontalface.xml");
- haarcascade_frontalface_alt_xml_filepath = Utils.getFilePath ("haarcascade_frontalface_alt.xml");
- Run ();
- #endif
- }
- #if UNITY_WEBGL && !UNITY_EDITOR
- private IEnumerator GetFilePath ()
- {
- var getFilePathAsync_lbpcascade_frontalface_xml_filepath_Coroutine = Utils.getFilePathAsync ("lbpcascade_frontalface.xml", (result) => {
- lbpcascade_frontalface_xml_filepath = result;
- });
- yield return getFilePathAsync_lbpcascade_frontalface_xml_filepath_Coroutine;
-
- var getFilePathAsync_haarcascade_frontalface_alt_xml_filepath_Coroutine = Utils.getFilePathAsync ("haarcascade_frontalface_alt.xml", (result) => {
- haarcascade_frontalface_alt_xml_filepath = result;
- });
- yield return getFilePathAsync_haarcascade_frontalface_alt_xml_filepath_Coroutine;
-
- getFilePath_Coroutine = null;
-
- Run ();
- }
- #endif
- private void Run ()
- {
- weightsPositionsSmoothing.Add (1);
- weightsSizesSmoothing.Add (0.5f);
- weightsSizesSmoothing.Add (0.3f);
- weightsSizesSmoothing.Add (0.2f);
-
- //parameters.minObjectSize = 96;
- //parameters.maxObjectSize = int.MaxValue;
- //parameters.scaleFactor = 1.1f;
- //parameters.minNeighbors = 2;
- parameters.maxTrackLifetime = 5;
-
- innerParameters.numLastPositionsToTrack = 4;
- innerParameters.numStepsToWaitBeforeFirstShow = 6;
- innerParameters.numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown = 3;
- innerParameters.numStepsToShowWithoutDetecting = 3;
- innerParameters.coeffTrackingWindowSize = 2.0f;
- innerParameters.coeffObjectSizeToTrack = 0.85f;
- innerParameters.coeffObjectSpeedUsingInPrediction = 0.8f;
- #if UNITY_ANDROID && !UNITY_EDITOR
- // Avoids the front camera low light issue that occurs in only some Android devices (e.g. Google Pixel, Pixel2).
- webCamTextureToMatHelper.avoidAndroidFrontCameraLowLightIssue = true;
- #endif
- webCamTextureToMatHelper.Initialize ();
- }
- /// <summary>
- /// Raises the webcam texture to mat helper initialized event.
- /// </summary>
- public void OnWebCamTextureToMatHelperInitialized ()
- {
- Debug.Log ("OnWebCamTextureToMatHelperInitialized");
-
- Mat webCamTextureMat = webCamTextureToMatHelper.GetMat ();
- texture = new Texture2D (webCamTextureMat.cols (), webCamTextureMat.rows (), TextureFormat.RGBA32, false);
- gameObject.GetComponent<Renderer> ().material.mainTexture = texture;
-
- gameObject.transform.localScale = new Vector3 (webCamTextureMat.cols (), webCamTextureMat.rows (), 1);
-
- Debug.Log ("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
- if (fpsMonitor != null) {
- fpsMonitor.Add ("width", webCamTextureMat.width ().ToString ());
- fpsMonitor.Add ("height", webCamTextureMat.height ().ToString ());
- fpsMonitor.Add ("orientation", Screen.orientation.ToString ());
- }
-
- float width = webCamTextureMat.width ();
- float height = webCamTextureMat.height ();
-
- float widthScale = (float)Screen.width / width;
- float heightScale = (float)Screen.height / height;
- if (widthScale < heightScale) {
- Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
- } else {
- Camera.main.orthographicSize = height / 2;
- }
-
- grayMat = new Mat (webCamTextureMat.rows (), webCamTextureMat.cols (), CvType.CV_8UC1);
- cascade = new CascadeClassifier ();
- cascade.load (lbpcascade_frontalface_xml_filepath);
- #if !UNITY_WSA_10_0
- if (cascade.empty ()) {
- Debug.LogError ("cascade file is not loaded. Please copy from “OpenCVForUnity/StreamingAssets/” to “Assets/StreamingAssets/” folder. ");
- }
- #endif
- InitThread ();
- }
- /// <summary>
- /// Raises the webcam texture to mat helper disposed event.
- /// </summary>
- public void OnWebCamTextureToMatHelperDisposed ()
- {
- Debug.Log ("OnWebCamTextureToMatHelperDisposed");
- #if !UNITY_WEBGL
- StopThread ();
- #else
- StopCoroutine ("ThreadWorker");
- #endif
- if (grayMat4Thread != null)
- grayMat4Thread.Dispose ();
- if (cascade4Thread != null)
- cascade4Thread.Dispose ();
- if (grayMat != null)
- grayMat.Dispose ();
- if (texture != null) {
- Texture2D.Destroy (texture);
- texture = null;
- }
- if (cascade != null)
- cascade.Dispose ();
-
- trackedObjects.Clear ();
- }
- /// <summary>
- /// Raises the webcam texture to mat helper error occurred event.
- /// </summary>
- /// <param name="errorCode">Error code.</param>
- public void OnWebCamTextureToMatHelperErrorOccurred (WebCamTextureToMatHelper.ErrorCode errorCode)
- {
- Debug.Log ("OnWebCamTextureToMatHelperErrorOccurred " + errorCode);
- }
- // Update is called once per frame
- void Update ()
- {
- if (webCamTextureToMatHelper.IsPlaying () && webCamTextureToMatHelper.DidUpdateThisFrame ()) {
-
- Mat rgbaMat = webCamTextureToMatHelper.GetMat ();
- Imgproc.cvtColor (rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
- Imgproc.equalizeHist (grayMat, grayMat);
- if (!shouldDetectInMultiThread) {
- grayMat.copyTo (grayMat4Thread);
- shouldDetectInMultiThread = true;
- }
- OpenCVForUnity.CoreModule.Rect[] rects;
-
- if (didUpdateTheDetectionResult) {
- didUpdateTheDetectionResult = false;
- //Debug.Log("DetectionBasedTracker::process: get _rectsWhereRegions were got from resultDetect");
- rectsWhereRegions = detectionResult.toArray ();
-
- rects = rectsWhereRegions;
- for (int i = 0; i < rects.Length; i++) {
- Imgproc.rectangle (rgbaMat, new Point (rects [i].x, rects [i].y), new Point (rects [i].x + rects [i].width, rects [i].y + rects [i].height), new Scalar (0, 0, 255, 255), 2);
- }
- } else {
- //Debug.Log("DetectionBasedTracker::process: get _rectsWhereRegions from previous positions");
- rectsWhereRegions = new Rect[trackedObjects.Count];
-
- for (int i = 0; i < trackedObjects.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) * innerParameters.coeffObjectSpeedUsingInPrediction,
- (center.y - center_prev.y) * innerParameters.coeffObjectSpeedUsingInPrediction);
-
- r.x += (int)Math.Round (shift.x);
- r.y += (int)Math.Round (shift.y);
- }
- rectsWhereRegions [i] = r;
- }
- rects = rectsWhereRegions;
- for (int i = 0; i < rects.Length; i++) {
- Imgproc.rectangle (rgbaMat, new Point (rects [i].x, rects [i].y), new Point (rects [i].x + rects [i].width, rects [i].y + rects [i].height), new Scalar (0, 255, 0, 255), 2);
- }
- }
- detectedObjectsInRegions.Clear ();
- if (rectsWhereRegions.Length > 0) {
-
- int len = rectsWhereRegions.Length;
- for (int i = 0; i < len; i++) {
- DetectInRegion (grayMat, rectsWhereRegions [i], detectedObjectsInRegions);
- }
- }
- UpdateTrackedObjects (detectedObjectsInRegions);
- GetObjects (resultObjects);
- rects = resultObjects.ToArray ();
- for (int i = 0; i < rects.Length; i++) {
- //Debug.Log ("detect faces " + rects [i]);
- Imgproc.rectangle (rgbaMat, new Point (rects [i].x, rects [i].y), new Point (rects [i].x + rects [i].width, rects [i].y + rects [i].height), new Scalar (255, 0, 0, 255), 2);
- }
- #if UNITY_WEBGL
- Imgproc.putText (rgbaMat, "WebGL platform does not support multi-threading.", new Point (5, rgbaMat.rows () - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar (255, 255, 255, 255), 1, Imgproc.LINE_AA, false);
- #endif
- Utils.fastMatToTexture2D (rgbaMat, texture);
- }
- }
- private void DetectInRegion (Mat img, Rect r, List<Rect> detectedObjectsInRegions)
- {
- Rect r0 = new Rect (new Point (), img.size ());
- Rect r1 = new Rect (r.x, r.y, r.width, r.height);
- Rect.inflate (r1, (int)((r1.width * innerParameters.coeffTrackingWindowSize) - r1.width) / 2,
- (int)((r1.height * innerParameters.coeffTrackingWindowSize) - r1.height) / 2);
- r1 = Rect.intersect (r0, r1);
-
- if (r1 != null && (r1.width <= 0) || (r1.height <= 0)) {
- Debug.Log ("DetectionBasedTracker::detectInRegion: Empty intersection");
- return;
- }
-
-
- int d = Math.Min (r.width, r.height);
- d = (int)Math.Round (d * innerParameters.coeffObjectSizeToTrack);
-
-
- MatOfRect tmpobjects = new MatOfRect ();
-
- Mat img1 = new Mat (img, r1);//subimage for rectangle -- without data copying
-
- cascade.detectMultiScale (img1, tmpobjects, 1.1, 2, 0 | Objdetect.CASCADE_DO_CANNY_PRUNING | Objdetect.CASCADE_SCALE_IMAGE | Objdetect.CASCADE_FIND_BIGGEST_OBJECT, new Size (d, d), new Size ());
-
-
- Rect[] tmpobjectsArray = tmpobjects.toArray ();
- int len = tmpobjectsArray.Length;
- for (int i = 0; i < len; i++) {
- Rect tmp = tmpobjectsArray [i];
- Rect curres = new Rect (new Point (tmp.x + r1.x, tmp.y + r1.y), tmp.size ());
- detectedObjectsInRegions.Add (curres);
- }
- }
- public Point CenterRect (Rect r)
- {
- return new Point (r.x + (r.width / 2), r.y + (r.height / 2));
- }
- private void InitThread ()
- {
- StopThread ();
-
- grayMat4Thread = new Mat ();
-
- cascade4Thread = new CascadeClassifier ();
- cascade4Thread.load (haarcascade_frontalface_alt_xml_filepath);
- #if !UNITY_WSA_10_0
- if (cascade4Thread.empty ()) {
- Debug.LogError ("cascade4Thread file is not loaded. Please copy from “OpenCVForUnity/StreamingAssets/” to “Assets/StreamingAssets/” folder. ");
- }
- #endif
-
- shouldDetectInMultiThread = false;
- #if !UNITY_WEBGL
- StartThread (ThreadWorker);
- #else
- StartCoroutine ("ThreadWorker");
- #endif
- }
- private void StartThread (Action action)
- {
- shouldStopThread = false;
- #if UNITY_METRO && NETFX_CORE
- System.Threading.Tasks.Task.Run(() => action());
- #elif UNITY_METRO
- action.BeginInvoke(ar => action.EndInvoke(ar), null);
- #else
- ThreadPool.QueueUserWorkItem (_ => action ());
- #endif
- Debug.Log ("Thread Start");
- }
- private void StopThread ()
- {
- if (!isThreadRunning)
- return;
- shouldStopThread = true;
- while (isThreadRunning) {
- //Wait threading stop
- }
- Debug.Log ("Thread Stop");
- }
- #if !UNITY_WEBGL
- private void ThreadWorker ()
- {
- isThreadRunning = true;
- while (!shouldStopThread) {
- if (!shouldDetectInMultiThread)
- continue;
- Detect ();
- shouldDetectInMultiThread = false;
- didUpdateTheDetectionResult = true;
- }
- isThreadRunning = false;
- }
-
-
- #else
- private IEnumerator ThreadWorker ()
- {
- while (true) {
- while (!shouldDetectInMultiThread) {
- yield return null;
- }
- Detect ();
- shouldDetectInMultiThread = false;
- didUpdateTheDetectionResult = true;
- }
- }
- #endif
- private void Detect ()
- {
- MatOfRect objects = new MatOfRect ();
- if (cascade4Thread != null)
- cascade4Thread.detectMultiScale (grayMat4Thread, objects, 1.1, 2, Objdetect.CASCADE_SCALE_IMAGE, // TODO: objdetect.CV_HAAR_SCALE_IMAGE
- new Size (grayMat4Thread.height () * 0.2, grayMat4Thread.height () * 0.2), new Size ());
- //Thread.Sleep(200);
- detectionResult = objects;
- }
- /// <summary>
- /// Raises the destroy event.
- /// </summary>
- void OnDestroy ()
- {
- webCamTextureToMatHelper.Dispose ();
- #if UNITY_WEBGL && !UNITY_EDITOR
- if (getFilePath_Coroutine != null) {
- StopCoroutine (getFilePath_Coroutine);
- ((IDisposable)getFilePath_Coroutine).Dispose ();
- }
- #endif
- }
- /// <summary>
- /// Raises the back button click event.
- /// </summary>
- public void OnBackButtonClick ()
- {
- SceneManager.LoadScene ("OpenCVForUnityExample");
- }
- /// <summary>
- /// Raises the play button click event.
- /// </summary>
- public void OnPlayButtonClick ()
- {
- webCamTextureToMatHelper.Play ();
- }
- /// <summary>
- /// Raises the pause button click event.
- /// </summary>
- public void OnPauseButtonClick ()
- {
- webCamTextureToMatHelper.Pause ();
- }
- /// <summary>
- /// Raises the stop button click event.
- /// </summary>
- public void OnStopButtonClick ()
- {
- webCamTextureToMatHelper.Stop ();
- }
- /// <summary>
- /// Raises the change camera button click event.
- /// </summary>
- public void OnChangeCameraButtonClick ()
- {
- webCamTextureToMatHelper.requestedIsFrontFacing = !webCamTextureToMatHelper.IsFrontFacing ();
- }
- //
- // tracker
- //
- private void GetObjects (List<Rect> result)
- {
- result.Clear ();
-
- for (int i = 0; i < trackedObjects.Count; i++) {
- Rect r = CalcTrackedObjectPositionToShow (i);
- if (r.area () == 0) {
- continue;
- }
- 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);
- }
- }
- private enum TrackedState : int
- {
- NEW_RECTANGLE = -1,
- INTERSECTED_RECTANGLE = -2
- }
- private void UpdateTrackedObjects (List<Rect> detectedObjects)
- {
- int N1 = (int)trackedObjects.Count;
- int N2 = (int)detectedObjects.Count;
-
- for (int i = 0; i < N1; i++) {
- trackedObjects [i].numDetectedFrames++;
- }
-
- int[] correspondence = new int[N2];
- for (int i = 0; i < N2; i++) {
- correspondence [i] = (int)TrackedState.NEW_RECTANGLE;
- }
-
-
- 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];
-
- for (int j = 0; j < N2; j++) {
- if (correspondence [j] >= 0) {
- //Debug.Log("DetectionBasedTracker::updateTrackedObjects: j=" + i + " is rejected, because it has correspondence=" + correspondence[j]);
- continue;
- }
- if (correspondence [j] != (int)TrackedState.NEW_RECTANGLE) {
- //Debug.Log("DetectionBasedTracker::updateTrackedObjects: j=" + j + " is rejected, because it is intersected with another rectangle");
- continue;
- }
-
- Rect r = Rect.intersect (prevRect, detectedObjects [j]);
- if (r != null && (r.width > 0) && (r.height > 0)) {
- //LOGD("DetectionBasedTracker::updateTrackedObjects: There is intersection between prevRect and detectedRect, r={%d, %d, %d x %d}",
- // r.x, r.y, r.width, r.height);
- correspondence [j] = (int)TrackedState.INTERSECTED_RECTANGLE;
-
- if (r.area () > bestArea) {
- //LOGD("DetectionBasedTracker::updateTrackedObjects: The area of intersection is %d, it is better than bestArea=%d", r.area(), bestArea);
- bestIndex = j;
- bestArea = (int)r.area ();
- }
- }
- }
-
- if (bestIndex >= 0) {
- //LOGD("DetectionBasedTracker::updateTrackedObjects: The best correspondence for i=%d is j=%d", i, bestIndex);
- correspondence [bestIndex] = i;
-
- for (int j = 0; j < N2; j++) {
- if (correspondence [j] >= 0)
- continue;
-
- Rect r = Rect.intersect (detectedObjects [j], detectedObjects [bestIndex]);
- if (r != null && (r.width > 0) && (r.height > 0)) {
- //LOGD("DetectionBasedTracker::updateTrackedObjects: Found intersection between "
- // "rectangles j=%d and bestIndex=%d, rectangle j=%d is marked as intersected", j, bestIndex, j);
- correspondence [j] = (int)TrackedState.INTERSECTED_RECTANGLE;
- }
- }
- } else {
- //LOGD("DetectionBasedTracker::updateTrackedObjects: There is no correspondence for i=%d ", i);
- curObject.numFramesNotDetected++;
- }
- }
-
- //LOGD("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)innerParameters.numLastPositionsToTrack) {
- trackedObjects [i].lastPositions.Remove (trackedObjects [i].lastPositions [0]);
- }
- trackedObjects [i].numFramesNotDetected = 0;
- } else if (i == (int)TrackedState.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.numFramesNotDetected > parameters.maxTrackLifetime)
- ||
- ((it.numDetectedFrames <= innerParameters.numStepsToWaitBeforeFirstShow)
- &&
- (it.numFramesNotDetected > innerParameters.numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown))) {
- //int numpos = (int)it.lastPositions.Count;
- //if (numpos > 0) UnityEngine.Debug.LogError("numpos > 0 is false");
- //Rect r = it.lastPositions [numpos - 1];
- //Debug.Log("DetectionBasedTracker::updateTrackedObjects: deleted object " + r.x + " " + r.y + " " + r.width + " " + r.height);
-
- trackedObjects.Remove (it);
-
- } else {
- t++;
- }
- }
- }
- private Rect CalcTrackedObjectPositionToShow (int i)
- {
- if ((i < 0) || (i >= trackedObjects.Count)) {
- Debug.Log ("DetectionBasedTracker::calcTrackedObjectPositionToShow: ERROR: wrong i=" + i);
- return new Rect ();
- }
- if (trackedObjects [i].numDetectedFrames <= innerParameters.numStepsToWaitBeforeFirstShow) {
- //Debug.Log("DetectionBasedTracker::calcTrackedObjectPositionToShow: " + "trackedObjects[" + i + "].numDetectedFrames=" + trackedObjects[i].numDetectedFrames + " <= numStepsToWaitBeforeFirstShow=" + innerParameters.numStepsToWaitBeforeFirstShow + " --- return empty Rect()");
- return new Rect ();
- }
- if (trackedObjects [i].numFramesNotDetected > innerParameters.numStepsToShowWithoutDetecting) {
- return new Rect ();
- }
-
- 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=tl;
- //c1=c1* 0.5f;//
- c1 = new Point (tl.x * 0.5f, tl.y * 0.5f);
- Point c2;
- //c2=br;
- //c2=c2*0.5f;
- c2 = new Point (br.x * 0.5f, br.y * 0.5f);
- //c1=c1+c2;
- c1 = new Point (c1.x + c2.x, c1.y + c2.y);
-
- //center=center+ (c1 * weightsPositionsSmoothing[j]);
- center = new Point (center.x + (c1.x * weightsPositionsSmoothing [j]), center.y + (c1.y * weightsPositionsSmoothing [j]));
- sum += weightsPositionsSmoothing [j];
- }
- //center *= (float)(1 / sum);
- 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=tl;
- //c1=c1* 0.5f;
- c1 = new Point (tl.x * 0.5f, tl.y * 0.5f);
- Point c2;
- //c2=br;
- //c2=c2*0.5f;
- c2 = new Point (br.x * 0.5f, br.y * 0.5f);
-
- //center=c1+c2;
- center = new Point (c1.x + c2.x, c1.y + c2.y);
- }
- //Point2f tl=center-(Point2f(w,h)*0.5);
- Point tl2 = new Point (center.x - (w * 0.5f), center.y - (h * 0.5f));
- //Rect res(cvRound(tl.x), cvRound(tl.y), cvRound(w), cvRound(h));
- Rect res = new Rect ((int)Math.Round (tl2.x), (int)Math.Round (tl2.y), (int)Math.Round (w), (int)Math.Round (h));
- //LOGD("DetectionBasedTracker::calcTrackedObjectPositionToShow: Result for i=%d: {%d, %d, %d x %d}", i, res.x, res.y, res.width, res.height);
-
- return res;
- }
- private struct Parameters
- {
- //public int minObjectSize;
- //public int maxObjectSize;
- //public float scaleFactor;
- //public int minNeighbors;
- public int maxTrackLifetime;
- //public int minDetectionPeriod; //the minimal time between run of the big object detector (on the whole frame) in ms (1000 mean 1 sec), default=0
- };
- private struct InnerParameters
- {
- public int numLastPositionsToTrack;
- public int numStepsToWaitBeforeFirstShow;
- public int numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown;
- public int numStepsToShowWithoutDetecting;
- public float coeffTrackingWindowSize;
- public float coeffObjectSizeToTrack;
- public float coeffObjectSpeedUsingInPrediction;
- };
- private class TrackedObject
- {
- public PositionsVector lastPositions;
- public int numDetectedFrames;
- public int numFramesNotDetected;
- public int id;
- static private int _id = 0;
- public TrackedObject (OpenCVForUnity.CoreModule.Rect rect)
- {
- lastPositions = new PositionsVector ();
- numDetectedFrames = 1;
- numFramesNotDetected = 0;
- lastPositions.Add (rect.clone ());
- _id = GetNextId ();
- id = _id;
- }
- static int GetNextId ()
- {
- _id++;
- return _id;
- }
- }
- }
- }
|