Thursday, 2 June 2016

Getting Started with EmguCv and Unity3D - Face detection using webcam

In this we will create a simple project to turn cube around by detecting face using a webcam

Tools I have used.

  1. Unity3D 5.3.3 personal edition
  2. EmguCv - emgucv-windesktop 3.1.0.2282
  3. A webcam
Getting Started

  1. Setup EmguCv for Unity3D by creating a new project (follow the below post if you have no idea how to set it up. http://sharewhatulearn.blogspot.in/2016/04/setting-up-emgucv-for-unity3d.html)
  2. Once you are done with all the basic setup go to Unity3D and create a Cube under GameObjects-> 3D Objects->Cube
  3. Set the cube x,y,z to 0 
  4. Select the main Camera and set its x=0, y=0, and Z= -3
  5. Next Create a Empty Game object GameObject-> Create Empty and name it as "FaceDetect"
  6. Create a new folder under Assets and name it as Scripts.
  7. Under Scripts folder Create a new C# Script file named "CameraScript"
  8. Again create another C# script file named "FaceDetectScript"
  9. Now select the "FaceDetect" Game Object and attach the "FaceDetectScript" to it.
  10. Now Select the Main Camera and attach the "CameraScript" to it.
  11. Copy the below script and paste it to CameraScriptusing UnityEngine;
    using System.Collections;

    public class CameraScript : MonoBehaviour
    {
        public GameObject faceDetect;
        public FaceDetectScript faceDetectScript;
        // Use this for initialization
        void Start()
        {
            faceDetectScript = faceDetect.GetComponent<FaceDetectScript>();
        }
        // Update is called once per frame
        void Update()
        {
            Vector2 facepos = faceDetectScript.facepos;
            Debug.Log("facepos:(" + facepos.x + " " + facepos.y + ")");
            float alpha = facepos.y * Mathf.PI;
            float beta = facepos.x * Mathf.PI;
            Vector3 pos;
            pos.x = -3.0f * Mathf.Sin(alpha) * Mathf.Cos(beta);
            pos.y = 3.0f * Mathf.Cos(alpha);
            pos.z = -3.0f * Mathf.Sin(alpha) * Mathf.Sin(beta);
            transform.position = pos;
            Vector3 relativePos = -transform.position;
            Quaternion rotation = Quaternion.LookRotation(relativePos);
            transform.rotation = rotation;
        }
    }
  12. Copy the below code and paste it to "FaceDetectScript" file
using UnityEngine;
    using System.Collections;
      using System.Drawing;
        using Emgu.CV;
          using Emgu.Util;
            using Emgu;
              using Emgu.CV.Util;
                using Emgu.CV.CvEnum;
                  using Emgu.CV.Structure;
                    using System.IO;
                      using System.Runtime.InteropServices;

                          public class FaceDetectScript : MonoBehaviour {
                            const int CAPTURE_WIDTH = 320;
                                  const int CAPTURE_HEIGHT = 240;
                                    public Vector2 facepos;
                                  private CascadeClassifier cascade;
                                        private Capture capture;
                                      public GameObject display;
                                        const double Scale = 1.04;
                                              const double ScaleFactor = 1.139;
                                                const int MinNeighbors = 2;
                                              // Use this for initialization
                                                void Start ()

                                                      {
                                                            cascade = new CascadeClassifier("Assets/haarcascade_frontalface_alt.xml");
                                                              
                                                                capture = new Capture();
                                                                  capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, CAPTURE_HEIGHT);
                                                                    capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, CAPTURE_WIDTH);
                                                                      Mat currentframe = (capture.QueryFrame());
                                                                        Debug.Log("width:" + currentframe.Width + " height:" + currentframe.Height);
                                                                          

                                                                      }

                                                                        // Update is called once per frame

                                                                          void Update () 

                                                                                {
                                                                              Image<Bgr, byte> frame = capture.QueryFrame().ToImage<Bgr, byte>();
                                                                                        //Display on top corner 
                                                                                          MemoryStream _memory = new MemoryStream();
                                                                                            frame.Bitmap.Save(_memory, frame.Bitmap.RawFormat);

                                                                                                Texture2D camera = new Texture2D(400, 400);
                                                                                                  if (frame != null)
                                                                                                    {
                                                                                                          camera.LoadImage(_memory.ToArray());
                                                                                                            display.GetComponent<Renderer>().material.mainTexture = camera;
                                                                                                          }
                                                                                                            //Display on top corner
                                                                                                      //moving the object
                                                                                                                Image<Gray, byte> gray = frame.Convert<Gray, byte>();

                                                                                                                    using (Image<Bgr, byte> imageFrame = capture.QueryFrame().ToImage<Bgr, byte>())
                                                                                                                      {
                                                                                                                            if (imageFrame != null)
                                                                                                                              {
                                                                                                                                    Image<Gray, byte> grayframe = imageFrame.Convert<Gray, byte>();
                                                                                                                                      Rectangle[] faces = cascade.DetectMultiScale(grayframe, 1.1, 10, Size.Empty, Size.Empty); //the actual face detection happens here
                                                                                                                        for (int i = 0; i < faces.Length; i++)
                                                                                                                                          {
                                                                                                                                                CircleF _circle = new CircleF();
                                                                                                                                                  float x = (int)(faces[i].X) + (faces[i].Width / 2);
                                                                                                                                                    float y = (int)(faces[i].Y) + (faces[i].Height / 2);
                                                                                                                                                      _circle.Radius = faces[i].Width / 2;
                                                                                                                                                        imageFrame.Draw(new CircleF(new PointF(x,y),_circle.Radius), new Bgr(100,100,256));

                                                                                                                                                            Debug.Log("Circle Position tracking:(" + x + " " + y + ")");
                                                                                                                                                              if (faces.Length > 0)
                                                                                                                                                                {
                                                                                                                                                                      facepos = new Vector2((x / 2.0f) / CAPTURE_WIDTH, (y / 2.0f) / CAPTURE_HEIGHT);
                                                                                                                                                                    }
                                                                                                                                                                    }      
                                                                                                                                                                  }            
                                                                                                                                                                }        
                                                                                                                                                          }

                                                                                                                                                              }
                                                                                                                                                              13. Now switch back to unity3D and select the Main Camera and Under the attached CameraScript drag and drop the FaceDetect game object on Face Detect field as shown in the below image.
                                                                                                                                                              14. Download and Copy the attached haarcascade_frontalface_alt.xml file and place it under the Assets Folder (link: https://github.com/gurunathanlakshmanan/EmguCV_Unity/blob/gh-pages/haarcascade_frontalface_alt.xml)
                                                                                                                                                              15. That's it now plug your webcam and run the game. 
                                                                                                                                                              16. Move your head so that you can see the Cube on your Game view too will rotate according.
                                                                                                                                                              17. That's it enjoy!

                                                                                                                                                              Thursday, 21 April 2016

                                                                                                                                                              Unity3D - Creating a simple Loading bar using AsyncOperation & UI Images using C#

                                                                                                                                                              This is to show how to create a simple loading progress using unity AsyncOperation.

                                                                                                                                                              Step 1; Create a UI image and name it as Progressbar and set the pivot point of the image to left center and width = 50 , height = 20.
                                                                                                                                                              Step 2: Create a new C# script and name it as LoadingBar.
                                                                                                                                                              Step 3 ; Copy and paste the below Code.
                                                                                                                                                              using UnityEngine;
                                                                                                                                                              using System.Collections;
                                                                                                                                                              using UnityEngine.UI;
                                                                                                                                                              using System;
                                                                                                                                                              using System.Collections.Generic;

                                                                                                                                                              public class LoadingBar : MonoBehaviour 
                                                                                                                                                              {
                                                                                                                                                                  public Image loader;
                                                                                                                                                                  RectTransform objectRectTransform;
                                                                                                                                                                  AsyncOperation async;
                                                                                                                                                                  float tempval;

                                                                                                                                                                  IEnumerator Start()
                                                                                                                                                                  {
                                                                                                                                                                      objectRectTransform = loader.GetComponent<RectTransform>();
                                                                                                                                                                      tempval = objectRectTransform.rect.width;
                                                                                                                                                                      Debug.Log(tempval);

                                                                                                                                                                      yield return new WaitForSeconds(0.1f);
                                                                                                                                                                      async = Application.LoadLevelAsync("Scene1");//add the next scene name that to be loaded
                                                                                                                                                                      yield return async;
                                                                                                                                                                  }
                                                                                                                                                                void Update()
                                                                                                                                                                  {
                                                                                                                                                                      try
                                                                                                                                                                      { 
                                                                                                                                                                          Debug.Log(async.progress);
                                                                                                                                                                          tempval += async.progress;
                                                                                                                                                                          loader.rectTransform.sizeDelta = new Vector2(tempval, 20f);
                                                                                                                                                                      
                                                                                                                                                                      }
                                                                                                                                                                      catch (NullReferenceException ex)
                                                                                                                                                                      {
                                                                                                                                                                          Debug.Log("Async not loaded!");
                                                                                                                                                                      }
                                                                                                                                                                  }

                                                                                                                                                              }
                                                                                                                                                              Step 4: Create a Empty Game object and drag the LoadingBar script on to it.
                                                                                                                                                              Step 5: In inspector add the ProgressBar image to variable loader.
                                                                                                                                                              Step 6 : Replace "Scene1" with next scene name that to be loaded in line   async = Application.LoadLevelAsync("Scene1"); on the above code
                                                                                                                                                              Step 7; Verify that you have added the current scene and next scene in Build settings.
                                                                                                                                                              Step 8: That's it. You can now play the scene and check it.

                                                                                                                                                              Wednesday, 13 April 2016

                                                                                                                                                              Setting Up EmguCV for Unity3D

                                                                                                                                                              In this we will see how to set up Emgucv for Unity3D

                                                                                                                                                              I am using

                                                                                                                                                              • Unity3D 5.3.3 personal edition
                                                                                                                                                              • EmguCv - emgucv-windesktop 3.1.0.2282.exe

                                                                                                                                                              download link : https://sourceforge.net/projects/emgucv/

                                                                                                                                                              Getting Started


                                                                                                                                                              1. Download and run the emgucv-windows setup exe. It will create a folder in C drive named as Emgu
                                                                                                                                                              2. Fire up Unity3D and create a new project.
                                                                                                                                                              3. Go to C:\Emgu\emgucv-windesktop 3.1.0.2282\bin  folder and copy all the .dll files including some .dll files from the folder x64( if you are using a 32bit or copy the files from x86 if you working on a 64bit)
                                                                                                                                                              4. Now open the new unity project folder which you have created.
                                                                                                                                                              5. Then open the Assets folder under new project and paste all the copied .dll files.
                                                                                                                                                              6. Now browse the folder where you have installed unity3D normally it should be under C:\Program Files\
                                                                                                                                                              7. Under this search for the file System.Drawing.dll. Copy this file and paste it along with the other .dll files under NewProject>>Assets folder
                                                                                                                                                              8. You need to add EmguCv path to System Environment Variables(Create a new system variable and also add the X64 directory under path variable too something similar to this ";Emgu\emgucv-windesktop 3.1.0.2282\x64")

                                                                                                                                                              9. That's it EmguCv is now setup for Unity3D. You can start playing around.


                                                                                                                                                              Wednesday, 6 April 2016

                                                                                                                                                              Detecting Webcam in Unity3D using C#

                                                                                                                                                              This is a basic tutorial explains how to detect webcam in Unity3D.


                                                                                                                                                              • Create a new project in Unity3D
                                                                                                                                                              • Create a new plane in unity3D under GameObject >> 3D Object >> Plane
                                                                                                                                                              • Set the Y rotation of plane to 180.
                                                                                                                                                              • Create a new folder named "Scripts" under assets.
                                                                                                                                                              • Create a new C# file under the Scripts folder and name it as DetectWebcam
                                                                                                                                                              • Drag the script over plane / Attach the script on the newly created plane

                                                                                                                                                              • Double click the DetectWebcam script file to launch Monodevelop/ Visual studio.
                                                                                                                                                              • Copy & paste the below code.

                                                                                                                                                              using UnityEngine;
                                                                                                                                                              using System.Collections;
                                                                                                                                                              public class DetectWebcam : MonoBehaviour
                                                                                                                                                              {
                                                                                                                                                                  void Start() 
                                                                                                                                                                  {
                                                                                                                                                                      WebCamDevice[] devices = WebCamTexture.devices;
                                                                                                                                                                      for( var i = 0 ; i < devices.Length ; i++ )
                                                                                                                                                                      {
                                                                                                                                                                          Debug.Log(devices[i].name);// Gets the list of available devices and prints its name
                                                                                                                                                                      }

                                                                                                                                                                      string deviceName = WebCamTexture.devices[0].name;
                                                                                                                                                                      WebCamTexture newTexture = new WebCamTexture(deviceName, 640, 360, 30);
                                                                                                                                                                      newTexture.Play();

                                                                                                                                                                      gameObject.GetComponent<Renderer>().material.mainTexture = newTexture;
                                                                                                                                                                          
                                                                                                                                                                  }
                                                                                                                                                              }
                                                                                                                                                              • Save the code and play the scene in Unity3D.
                                                                                                                                                              • That's it 

                                                                                                                                                              Setting Up OPenCv & Tesseract for Visual Studio 2013 -OCR

                                                                                                                                                              Step 1: Download all the required tools
                                                                                                                                                              • OpenCv - https://sourceforge.net/projects/opencvlibrary/files/opencv-win/3.1.0/opencv-3.1.0.exe/download
                                                                                                                                                              • Tesseract - https://github.com/tesseract-ocr/tesseract/wiki/Downloads
                                                                                                                                                              • Visual Studio 2013
                                                                                                                                                              Step 2 : Setting up OpenCV
                                                                                                                                                              1. Extract the downloaded OpenCv installer to C drive or any preferred drives.
                                                                                                                                                              Step 3: Setting up Tesseract

                                                                                                                                                              Copy all the downloaded files to C drive where you have already extracted OpenCv. 

                                                                                                                                                              Step 4: Setting up VS 2013

                                                                                                                                                              Run Visual Studio 2013 set to get it installed.
                                                                                                                                                              By this step I hope all the required tools are downloaded and got it installed/copied to respective drives.

                                                                                                                                                              Step 4: Setting up environment variables
                                                                                                                                                              • Right click on My Computer>> properties
                                                                                                                                                              • Then click on Advanced  System Settings
                                                                                                                                                              • Click on Environment Variables under Advanced tab.
                                                                                                                                                              • Then click on new under System variables
                                                                                                                                                              1. Add variable name as OPENCV_DIR and variable value as C:\opencv\build\x64\vc12\bin (this is the path of openCv bin folder check where you have copied your openCv files)
                                                                                                                                                              2. Create one more new System variable and fill the details as variable name as TESSDATA_PREFIX variable value as C:\Tesseract-Build\tesseract-vs2013\ (this is the path of tesseract bin folder check where you have copied your tesseract files)
                                                                                                                                                              3. Now search for Path variable under System variables and add the following followed by a ;C:\opencv\build\x64\vc12\bin;C:\Tesseract-Build\tesseract-vs2013\build\lib\x64
                                                                                                                                                              Step 6: Configuring OpenCv and Tesseract for VS 2013 
                                                                                                                                                              • Launch VS 2013.
                                                                                                                                                              • File >> New >> Project(Ctrl+Shift+N)
                                                                                                                                                              • Choose Visual C++ >> Win32 Console Application
                                                                                                                                                              • Give a name for your new project and click OK to continue

                                                                                                                                                              • Click Next to continue
                                                                                                                                                              • Click Finish to complete
                                                                                                                                                              • Right over the project under Solution Explorer and select the option Properties(Alt + Enter)
                                                                                                                                                              • Under C/C++ .. select the Additional Include Directories and add the path of Tesseract and OpenCv include folders something as below
                                                                                                                                                              C:\Tesseract-Build\tesseract-vs2013\include
                                                                                                                                                              C:\Tesseract-Build\tesseract-vs2013
                                                                                                                                                              C:\opencv\build\include
                                                                                                                                                              • Then select General under Linker and add all the library paths for tesseract and OpenCv, something as below. You can check the tesseract and OpenCv folders which you have already copied to your C drive to get the exact path
                                                                                                                                                              C:\Tesseract-Build\tesseract-vs2013\build\lib\x64
                                                                                                                                                              C:\Tesseract-Build\tesseract-vs2013\lib
                                                                                                                                                              C:\opencv\build\x64\vc12\lib\
                                                                                                                                                              $(OPENCV_DIR)\lib
                                                                                                                                                              • Then Move on to Input under Linker and add the following, which can be found under C:\opencv\build\x64\vc12\lib and C:\Tesseract-Build\tesseract-vs2013\build\lib\x64

                                                                                                                                                              opencv_world310.lib
                                                                                                                                                              opencv_world310d.lib
                                                                                                                                                              liblept168.lib
                                                                                                                                                              libtesseract302.lib
                                                                                                                                                              • That's it now OPenCv & Tesseract is successfully configured for Visual Studio 2013.
                                                                                                                                                              • Note - You need to configure similarly whenever you create a new project.
                                                                                                                                                              • So Let us test it now
                                                                                                                                                              • Save the below hello world  image and copy it to your project folder something similar as below path: Visual Studio 2013\Projects\openCvtest\openCvtest

                                                                                                                                                              • Now create a new C++ file by right clicking on source files
                                                                                                                                                              • Now open the newly created C++ file and paste the below code

                                                                                                                                                              #include "opencv2/core/core.hpp"
                                                                                                                                                              #include"opencv2/highgui/highgui.hpp"
                                                                                                                                                              using namespace cv;
                                                                                                                                                              using namespace std;
                                                                                                                                                              #include <iostream>

                                                                                                                                                              int main(int argc, const char** argv)
                                                                                                                                                              {
                                                                                                                                                              Mat img = imread("helloworld.jpg", CV_LOAD_IMAGE_UNCHANGED);

                                                                                                                                                              namedWindow("MyWindow", CV_WINDOW_AUTOSIZE); //create a window with the name "MyWindow"
                                                                                                                                                              imshow("MyWindow", img); //display the image which is stored in the 'img' in the "MyWindow" window

                                                                                                                                                              waitKey(0); //wait infinite time for a keypress

                                                                                                                                                              return 0;
                                                                                                                                                              }
                                                                                                                                                              • Then press Ctrl+F5 to compile the code
                                                                                                                                                              • This window opens up an image window with Hello World Text as shown below.
                                                                                                                                                              • That's it you have successfully configured openCv and tesseract for VS2013