3DSelfie  Hansjoerg Hofer (1026632), Sebastian Metzler (0927550)
Snake.cs
Go to the documentation of this file.
1 using UnityEngine;
2 using System;
3 using CSML;
4 
10 public class Snake : MonoBehaviour {
11 
12  Renderer _renderer;
13  Texture2D _I;
14 
15  public Texture2D _dIdx;
16  public Texture2D _dIdy;
17 
18  Matrix _Vx;
19  Matrix _Vy;
20 
21  Matrix _initVx;
22  Matrix _initVy;
23 
24  public float _alpha = 0.01f;
25  public float _beta = 0.001f;
26  public float _gamma = 1.5f;
27  public float _kappa = 0.9f;
28 
29  private float _touchTime = -0.5f;
30 
31  Matrix _AInv;
32 
33  bool init = true;
34 
40  void OnEnable () {
41  _renderer = GetComponent<Renderer> ();
42  _I = GameObject.Find ("2texCam").GetComponent<grabPicture> ().binaryImageAll;
43 
44  _Vx = new Matrix();
45  _Vy = new Matrix();
46 
47  _initVx = new Matrix();
48  _initVy = new Matrix();
49 
50  colorIndex = 0;
51  }
52 
56  void Update () {}
57 
65  public Vector3[] GetSnakeWorldPoints() {
66  Vector3[] points = new Vector3[_Vx.RowCount];
67 
68  for(int i = 0; i < _Vx.RowCount; i++) {
69  points[i] = new Vector3((float)_Vx[i + 1].Re, (float)_Vy[i + 1].Re, 0.0f);
70  points[i] = GameObject.Find("2texCam").GetComponent<Camera>().ScreenToWorldPoint(points[i]);
71  }
72  return points;
73  }
74 
82  public Vector3[] GetStartWorldPoints() {
83  Vector3[] points = new Vector3[_Vx.RowCount];
84 
85  for(int i = 0; i < _Vx.RowCount; i++) {
86  points[i] = new Vector3((float)_initVx[i + 1].Re, (float)_initVy[i + 1].Re, 0.0f);
87  points[i] = GameObject.Find("2texCam").GetComponent<Camera>().ScreenToWorldPoint(points[i]);
88  }
89  return points;
90  }
91 
92  Vector3 startPoints;
93 
101  public void SetControlPoints(Vector3[] controlPoints){
102 
103  _initVx = new Matrix();
104  _initVy = new Matrix();
105 
106  foreach (Vector3 cp in controlPoints) {
107  RaycastHit hit;
108  Vector3 position = GameObject.Find("2texCam").GetComponent<Camera>().WorldToScreenPoint(cp);
109 
110  Matrix tmpX, tmpY;
111  if (Physics.Raycast (GameObject.Find("2texCam").GetComponent<Camera>().ScreenPointToRay (position), out hit)) {
112  Vector2 uv = hit.textureCoord;
113 
114  tmpX = new Matrix (new double[] {uv.x * _I.width});
115  tmpY = new Matrix (new double[] {uv.y * _I.height});
116 
117  if (_initVx.RowCount > 0) {
118  _initVx = Matrix.HorizontalConcat (_initVx, tmpX);
119  _initVy = Matrix.HorizontalConcat (_initVy, tmpY);
120  } else {
121  _initVx = tmpX;
122  _initVy = tmpY;
123  }
124  }
125  }
126  }
127 
133  public void DisplayImagePlane(bool display) {
134  _renderer.enabled = display;
135  }
136 
140  public void ShowContour () {
141  drawContour (_I, _Vx, _Vy, 1.0f);
142  }
143 
144  int colorIndex = 0;
156  Texture2D drawContour(Texture2D image, Matrix contourX, Matrix contourY, float alpha) {
157  Color[] c = new Color[] {
158  Color.blue, Color.cyan, Color.green, Color.yellow, Color.red,
159  Color.magenta, Color.gray
160  };
161  int N = contourX.RowCount;
162  int x, y, ci = 0;
163  for (int i = 0; i < N; i++) {
164 
165  c[ci] = c[ci] * alpha;
166 
167  x = (int)Math.Round(contourX[i + 1].Re);
168  y = (int)Math.Round(contourY[i + 1].Re);
169  ci = colorIndex;
170 
171  image.SetPixel(x, y, c[ci]);
172 
173  image.SetPixel(x +1, y, c[ci]);
174  image.SetPixel(x, y +1,c[ci]);
175  image.SetPixel(x -1, y, c[ci]);
176  image.SetPixel(x, y -1,c[ci]);
177 
178  image.SetPixel(x +1, y +1,c[ci]);
179  image.SetPixel(x -1, y +1,c[ci]);
180  image.SetPixel(x -1, y -1,c[ci]);
181  image.SetPixel(x +1, y -1,c[ci]);
182 
183  image.SetPixel(x +1, y +2,c[ci]);
184  image.SetPixel(x -1, y +2,c[ci]);
185  image.SetPixel(x -1, y -2,c[ci]);
186  image.SetPixel(x +1, y -2,c[ci]);
187  image.SetPixel(x +2, y +1,c[ci]);
188  image.SetPixel(x -2, y +1,c[ci]);
189  image.SetPixel(x -2, y -1,c[ci]);
190  image.SetPixel(x +2, y -1,c[ci]);
191 
192  image.SetPixel(x +2, y +2,c[ci]);
193  image.SetPixel(x -2, y +2,c[ci]);
194  image.SetPixel(x -2, y -2,c[ci]);
195  image.SetPixel(x +2, y -2,c[ci]);
196 
197  image.SetPixel(x +3, y +3,c[ci]);
198  image.SetPixel(x -3, y +3,c[ci]);
199  image.SetPixel(x -3, y -3,c[ci]);
200  image.SetPixel(x +3, y -3,c[ci]);
201  }
202  image.Apply ();
203 
204 
205  colorIndex = (colorIndex + 1)% c.Length;
206  return image;
207  }
208 
218  public void UpdateSnake(int iterations, bool drawSteps) {
219 
220  GameObject dFdxQuad = GameObject.Find("dFdxCam");
221 
222  dFdxQuad.GetComponent<Render2Texture> ().enabled = true;
223  _dIdx = dFdxQuad.GetComponent<Render2Texture>().textOut;
224 
225  GameObject dFdyQuad = GameObject.Find("dFdyCam");
226 
227  dFdyQuad.GetComponent<Render2Texture> ().enabled = true;
228  _dIdy = dFdyQuad.GetComponent<Render2Texture>().textOut;
229 
230  Color[] dVdx = _dIdx.GetPixels ();
231  Color[] dVdy = _dIdy.GetPixels ();
232 
233  Matrix vfx,vfy;
234 
235  if(!drawSteps)
236  drawContour(_I, _Vx, _Vy, 1.0f);
237  for (int i = 0; i < iterations; i++) {
238 
239  vfx = interpolate(dVdx, _Vx, _Vy);
240  vfy = interpolate(dVdy, _Vx, _Vy);
241 
242  _Vx = _AInv * ( _gamma * _Vx - _kappa * vfx);
243  _Vy = _AInv * ( _gamma * _Vy - _kappa * vfy);
244 
245  if(i % 50 == 0 && drawSteps) {
246  drawContour(_I, _Vx, _Vy, 1.0f);
247  }
248  }
249  if(!drawSteps)
250  drawContour(_I, _Vx, _Vy, 1.0f);
251  }
252 
264  Matrix interpolate(Color[] gradient, Matrix Vx, Matrix Vy) {
265 
266  int N = Vx.RowCount;
267  double[] p = new double[N];
268  Color d;
269 
270  int x, y = 0;
271  for (int i = 0; i < N; i++) {
272  x = (int)Math.Round(Vx[i + 1].Re);
273  y = (int)Math.Round(Vy[i + 1].Re);
274 
275  int j = x + y * _I.width;
276  if(j > gradient.Length)
277  j = gradient.Length-1;
278 
279  if(j<0)
280  j=0;
281 
282  d = gradient[j];
283 
284  p[i] = (((d.r * 2.0) - 1.0) + ((d.g * 2.0) - 1.0) + ((d.b * 2.0) - 1.0)) / 3.0;
285  p[i] *= -255.0;
286  p[i] -= 1.0;
287 
288  }
289 
290  return new Matrix (p);
291  }
292 
300  public void InitSnake(bool expanding = false) {
301 
302  _Vx = _initVx.Clone ();
303  _Vy = _initVy.Clone ();
304 
305  int N = _Vx.RowCount;
306  Matrix alphaV = _alpha * Matrix.Ones (1, N);
307  Matrix betaV = _beta * Matrix.Ones (1, N);
308  Matrix gammaV = _gamma * Matrix.Ones (1, N);
309 
310  //Invert alpha to get a expanding Snake
311  if(expanding) {
312  alphaV *= -1.0f;
313  }
314 
315  Matrix diag1 = 2 * alphaV + 6 * betaV;
316  Matrix diag2 = -alphaV - 4 * betaV;
317  Matrix diag3 = betaV;
318 
319  /*
320  creates a matrix in the form:
321 
322  -2a-6b a+4b -b 0 0 0 ... -b a+4b
323 
324  a+4b -2a-6b a+4b -b 0 0 ... 0 -b
325 
326  -b a+4b -2a-6b a+4b -b 0 ... 0 0
327 
328  0 -b a+4b -2a-6b a+4b -b ... 0 0
329 
330  0 0 -b a+4b -2a-6b a+4b ... 0 0
331 
332  ... ... ... ... ... ... ... ... ...
333 
334  -b 0 0 0 0 0 ... -2a-6b a+4b
335 
336  a+4b -b 0 0 0 0 ... a+4b -2a-6b
337  */
338 
339  Matrix A = Matrix.Diag (diag1);
340  Matrix Diag2 = Matrix.Diag (diag2, 1) + Matrix.Diag (diag2, -1);
341  Matrix Diag2a = Matrix.Diag (diag2, N - 1) + Matrix.Diag (diag2, -(N - 1));
342 
343  Matrix Diag3 = Matrix.Diag (diag3, 2) + Matrix.Diag (diag3, -2);
344  Matrix Diag3a = Matrix.Diag (diag3, N - 2) + Matrix.Diag (diag3, -(N - 2));
345 
346  A += Diag2.Extract (1, N, 1, N);
347  A += Diag2a.Extract (1, N, 1, N);
348  A += Diag3.Extract (1, N, 1, N);
349  A += Diag3a.Extract (1, N, 1, N);
350  A += Matrix.Diag (gammaV);
351 
352  _AInv = A.Inverse ();
353  }
354 }
Texture2D _dIdy
Definition: Snake.cs:16
float _kappa
Definition: Snake.cs:27
float _alpha
Definition: Snake.cs:24
void DisplayImagePlane(bool display)
Renders the snake image plane.
Definition: Snake.cs:133
Render2Texture Script.
void SetControlPoints(Vector3[] controlPoints)
Sets the contour.
Definition: Snake.cs:101
Vector3[] GetSnakeWorldPoints()
Gets the resulting contour in world coordinates.
Definition: Snake.cs:65
float _gamma
Definition: Snake.cs:26
Snake script.
Definition: Snake.cs:10
void InitSnake(bool expanding=false)
Initializes the snake with the given contour.
Definition: Snake.cs:300
void UpdateSnake(int iterations, bool drawSteps)
Executes the snake algorithm.
Definition: Snake.cs:218
float _beta
Definition: Snake.cs:25
void ShowContour()
Renders the current contour state on the image plane.
Definition: Snake.cs:140
Texture2D _dIdx
Definition: Snake.cs:15
Vector3[] GetStartWorldPoints()
Gets the start contour in world coordinates.
Definition: Snake.cs:82