Skip to content

Instantly share code, notes, and snippets.

@jhorikawa
Created October 31, 2015 06:14
Show Gist options
  • Save jhorikawa/314295541a93cdf46e07 to your computer and use it in GitHub Desktop.
Save jhorikawa/314295541a93cdf46e07 to your computer and use it in GitHub Desktop.
Unity + OpenCVでオプティカルフローを実現してみる ref: http://qiita.com/jhorikawa/items/fafee3373eb3ccef02c8
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;
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;
}
}
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 ();
}
}
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