Created
October 31, 2015 06:14
-
-
Save jhorikawa/314295541a93cdf46e07 to your computer and use it in GitHub Desktop.
Unity + OpenCVでオプティカルフローを実現してみる ref: http://qiita.com/jhorikawa/items/fafee3373eb3ccef02c8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.Linq; | |
using Emgu.CV.CvEnum; | |
using UnityEngine; | |
using System; | |
using System.Drawing; | |
using System.Collections; | |
using System.Text; | |
using Emgu.CV; | |
using Emgu.CV.Structure; | |
using Emgu.CV.Util; | |
using System.Runtime.InteropServices; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private WebCamTexture webcamTexture; | |
private WebCamDevice[] devices; | |
private int wSize; | |
private int hSize; | |
private FlipType flip = FlipType.Vertical; | |
void Start () { | |
SetupWebCamera (); | |
} | |
void SetupWebCamera(){ | |
WebCamDevice[] devices = WebCamTexture.devices; | |
int cameraCount = devices.Length; | |
if (cameraCount == 0) | |
{ | |
Image<Bgr, Byte> img = new Image<Bgr, byte>(640, 240); | |
CvInvoke.PutText(img, String.Format("{0} camera found", devices.Length), new System.Drawing.Point(10, 60), Emgu.CV.CvEnum.FontFace.HersheyDuplex,1.0, new MCvScalar(0, 255, 0)); | |
Texture2D texture = TextureConvert.ImageToTexture2D(img, flip); | |
this.GetComponent<GUITexture>().texture = texture; | |
this.GetComponent<GUITexture>().pixelInset = new Rect(-img.Width/2, -img.Height/2, img.Width, img.Height); | |
vectorFields = new Vector2[img.Width * img.Height]; | |
wSize = img.Width; | |
hSize = img.Height; | |
} | |
else | |
{ | |
webcamTexture = new WebCamTexture(devices[0].name); | |
webcamTexture.Play(); | |
CvInvoke.CheckLibraryLoaded(); | |
vectorFields = new Vector2[webcamTexture.width * webcamTexture.height]; | |
wSize = webcamTexture.width; | |
hSize = webcamTexture.height; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public GameObject plane; | |
private Texture2D resultTexture; | |
private Color32[] data; //holds pixel data for webcam | |
private byte[] bytes; | |
private Image<Gray,Byte> prevImage; | |
private Image<Gray,Byte> currentImage; | |
private Vector2[] vectorFields; | |
void Update () { | |
DrawCamera (); | |
} | |
void DrawCamera(){ | |
if (webcamTexture != null && webcamTexture.didUpdateThisFrame) | |
{ | |
if (data == null || (data.Length != webcamTexture.width * webcamTexture.height)) | |
{ | |
data = new Color32[webcamTexture.width * webcamTexture.height]; | |
} | |
webcamTexture.GetPixels32(data); | |
if (bytes == null || bytes.Length != data.Length*3) | |
{ | |
bytes = new byte[data.Length*3]; | |
} | |
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); | |
GCHandle resultHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); | |
using (Image<Bgra, byte> image = new Image<Bgra, byte>(webcamTexture.width, webcamTexture.height, webcamTexture.width * 4, handle.AddrOfPinnedObject())) | |
using (Mat bgr = new Mat(webcamTexture.height, webcamTexture.width, DepthType.Cv8U, 3, resultHandle.AddrOfPinnedObject(), webcamTexture.width * 3)) | |
{ | |
CvInvoke.CvtColor(image.Convert<Gray,Byte>(), bgr, ColorConversion.Gray2Bgr); | |
CvInvoke.BitwiseNot(bgr, bgr); | |
if (flip != FlipType.None) | |
CvInvoke.Flip(bgr, bgr, flip); | |
currentImage = image.Convert<Gray,Byte>(); | |
currentImage = currentImage.Resize(0.3f,Inter.Linear); | |
currentImage = currentImage.Flip(FlipType.Horizontal); | |
vectorFields = new Vector2[currentImage.Width * currentImage.Height]; | |
wSize = currentImage.Width; | |
hSize = currentImage.Height; | |
CalculateOpticalFlow (); | |
} | |
handle.Free(); | |
resultHandle.Free(); | |
if (resultTexture == null || resultTexture.width != webcamTexture.width || | |
resultTexture.height != webcamTexture.height) | |
{ | |
resultTexture = new Texture2D(webcamTexture.width, webcamTexture.height, TextureFormat.RGB24, false); | |
} | |
resultTexture.LoadRawTextureData(bytes); | |
resultTexture.Apply(); | |
plane.GetComponent<MeshRenderer>().material.mainTexture = resultTexture; | |
} | |
} | |
void CalculateOpticalFlow(){ | |
if (currentImage != null) { | |
GCHandle vectorHandle = GCHandle.Alloc (vectorFields, GCHandleType.Pinned); | |
using (Mat flowMat = new Mat(currentImage.Height, currentImage.Width, DepthType.Cv32F,2, vectorHandle.AddrOfPinnedObject(),currentImage.Width*8)) { | |
if (prevImage != null) { | |
CvInvoke.CalcOpticalFlowFarneback (prevImage, currentImage, flowMat, 0.5, 3, 15, 3, 5, 1.2, 0); | |
} | |
prevImage = currentImage; | |
} | |
vectorHandle.Free (); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void OnDrawGizmos(){ | |
Vector3 minPos = plane.GetComponent<BoxCollider>().bounds.min; | |
Vector3 maxPos = plane.GetComponent<BoxCollider>().bounds.max; | |
if (vectorFields != null && vectorFields.Length == wSize*hSize) { | |
int resolution = 5; | |
for (int i=0; i<hSize; i+=resolution) { | |
for (int n=0; n<wSize; n+=resolution) { | |
Vector2 v = vectorFields [wSize * i + n]; | |
Gizmos.color = Color.red; | |
Vector3 start = new Vector3(minPos.x+n*1f/wSize*(maxPos.x-minPos.x),0,minPos.z+i*1f/hSize*(maxPos.z-minPos.z)); | |
Gizmos.DrawLine (start,start + new Vector3 (v.x/10f, 0, v.y/10f)); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment