Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ObjectMap.cs
2using System;
3using System.Collections.Generic;
4
5namespace IdApp.Cv.Objects
6{
10 public class ObjectMap : Matrix<ushort>
11 {
12 private readonly Dictionary<ushort, ObjectInformation> objectsById = new Dictionary<ushort, ObjectInformation>();
13 private readonly ObjectInformation[] objects;
14 private readonly IMatrix image;
15
21 public ObjectMap(Matrix<float> M, float Threshold)
22 : base(M.Width, M.Height)
23 {
24 this.image = Image;
25
26 int y, h = M.Height;
27 int x, w = M.Width;
28 int SrcIndex = M.Start;
29 int SrcSkip = M.Skip;
30 int DestIndex = 0;
31 float[] Src = M.Data;
32 ushort[] Dest = this.Data;
33 float v;
35 ushort Obj;
36
37 for (y = 0; y < h; y++, SrcIndex += SrcSkip)
38 {
39 for (x = 0; x < w; x++, DestIndex++)
40 {
41 v = Src[SrcIndex++];
42 if (v >= Threshold)
43 {
44 Obj = Dest[DestIndex];
45 if (Obj == 0)
46 {
47 Obj = (ushort)this.objectsById.Count;
48 Info = new ObjectInformation(Obj, x, y, this);
49 this.objectsById[Obj] = Info;
50 this.FloodFill(x, y, M, Threshold, Info);
51 }
52 }
53 }
54 }
55
56 this.objects = new ObjectInformation[this.objectsById.Count];
57 this.objectsById.Values.CopyTo(this.objects, 0);
58 }
59
60 private void FloodFill(int x, int y, Matrix<float> M, float Threshold, ObjectInformation Info)
61 {
62 int SrcIndex = M.StartIndex(0, y);
63 int DestIndex = this.StartIndex(0, y);
64 float[] Src = M.Data;
65 ushort[] Dest = this.Data;
66 int x1 = x;
67 int x2 = x;
68 int w = M.Width;
69 int h = M.Height - 1;
70 int SrcRow = M.RowSize;
71 int DestRow = this.RowSize;
72 ushort Nr = (ushort)(Info.Nr + 1);
73 int si, di;
74
75 while (x1 > 0 && Src[SrcIndex + x1 - 1] >= Threshold && Dest[DestIndex + x1 - 1] == 0)
76 x1--;
77
78 while (x2 < w - 1 && Src[SrcIndex + x2 + 1] >= Threshold && Dest[DestIndex + x2 + 1] == 0)
79 x2++;
80
81 Info.AddPixels(x1, x2, y);
82
83 x = x1;
84 di = DestIndex + x;
85 Dest[di] = (ushort)(Nr | 0x8000);
86 x++;
87 di++;
88
89 while (x < x2)
90 {
91 Dest[di] = Nr;
92 x++;
93 di++;
94 }
95
96 Dest[di] = (ushort)(Nr | 0x8000);
97
98 for (x = x1, si = SrcIndex + x, di = DestIndex + x; x <= x2; x++, si++, di++)
99 {
100 if (y > 0)
101 {
102 if (Src[si - SrcRow] >= Threshold)
103 {
104 if (Dest[di - DestRow] == 0)
105 this.FloodFill(x, y - 1, M, Threshold, Info);
106 }
107 else
108 Dest[di] |= 0x4000;
109 }
110
111 if (y < h)
112 {
113 if (Src[si + SrcRow] >= Threshold)
114 {
115 if (Dest[di + DestRow] == 0)
116 this.FloodFill(x, y + 1, M, Threshold, Info);
117 }
118 else
119 Dest[di] |= 0x4000;
120 }
121 }
122 }
123
124
130 public ObjectMap(Matrix<int> M, int Threshold)
131 : base(M.Width, M.Height)
132 {
133 this.image = Image;
134
135 int y, h = M.Height;
136 int x, w = M.Width;
137 int SrcIndex = M.Start;
138 int SrcSkip = M.Skip;
139 int DestIndex = 0;
140 int[] Src = M.Data;
141 ushort[] Dest = this.Data;
142 int v;
144 ushort Obj;
145
146 for (y = 0; y < h; y++, SrcIndex += SrcSkip)
147 {
148 for (x = 0; x < w; x++, DestIndex++)
149 {
150 v = Src[SrcIndex++];
151 if (v >= Threshold)
152 {
153 Obj = Dest[DestIndex];
154 if (Obj == 0)
155 {
156 Obj = (ushort)this.objectsById.Count;
157 Info = new ObjectInformation(Obj, x, y, this);
158 this.objectsById[Obj] = Info;
159 this.FloodFill(x, y, M, Threshold, Info);
160 }
161 }
162 }
163 }
164
165 this.objects = new ObjectInformation[this.objectsById.Count];
166 this.objectsById.Values.CopyTo(this.objects, 0);
167 }
168
169 private void FloodFill(int x, int y, Matrix<int> M, int Threshold, ObjectInformation Info)
170 {
171 int SrcIndex = M.StartIndex(0, y);
172 int DestIndex = this.StartIndex(0, y);
173 int[] Src = M.Data;
174 ushort[] Dest = this.Data;
175 int x1 = x;
176 int x2 = x;
177 int w = M.Width;
178 int h = M.Height - 1;
179 int SrcRow = M.RowSize;
180 int DestRow = this.RowSize;
181 ushort Nr = (ushort)(Info.Nr + 1);
182 int si, di;
183
184 while (x1 > 0 && Src[SrcIndex + x1 - 1] >= Threshold && Dest[DestIndex + x1 - 1] == 0)
185 x1--;
186
187 while (x2 < w - 1 && Src[SrcIndex + x2 + 1] >= Threshold && Dest[DestIndex + x2 + 1] == 0)
188 x2++;
189
190 Info.AddPixels(x1, x2, y);
191
192 x = x1;
193 di = DestIndex + x;
194 Dest[di] = (ushort)(Nr | 0x8000);
195 x++;
196 di++;
197
198 while (x < x2)
199 {
200 Dest[di] = Nr;
201 x++;
202 di++;
203 }
204
205 Dest[di] = (ushort)(Nr | 0x8000);
206
207 for (x = x1, si = SrcIndex + x, di = DestIndex + x; x <= x2; x++, si++, di++)
208 {
209 if (y > 0)
210 {
211 if (Src[si - SrcRow] >= Threshold)
212 {
213 if (Dest[di - DestRow] == 0)
214 this.FloodFill(x, y - 1, M, Threshold, Info);
215 }
216 else
217 Dest[di] |= 0x4000;
218 }
219
220 if (y < h)
221 {
222 if (Src[si + SrcRow] >= Threshold)
223 {
224 if (Dest[di + DestRow] == 0)
225 this.FloodFill(x, y + 1, M, Threshold, Info);
226 }
227 else
228 Dest[di] |= 0x4000;
229 }
230 }
231 }
232
236 public IMatrix Image => this.image;
237
241 public int NrObjects => this.objectsById.Count;
242
248 public ObjectInformation this[ushort Nr] => this.objectsById[Nr];
249
250 internal Point[] FindContour(int X0, int Y0, int Nr)
251 {
252 List<Point> Result = new List<Point>();
253 LinkedList<Rec> History = new LinkedList<Rec>();
254 Point P;
255 int Dir = 0; // Right
256 int x = X0;
257 int y = Y0;
258 int i;
259 int Index = this.StartIndex(X0, Y0);
260 int Index1;
261 int RowSize = this.RowSize;
262 int w = this.Width;
263 int h = this.Height;
264 ushort[] Data = this.Data;
265 ushort v;
266 int dx, dy;
267 int x1, y1;
268
269 Nr++;
270
271 Result.Add(P = new Point(X0, Y0));
272 History.AddLast(new Rec(P, Dir));
273 Data[Index] &= 0x3fff;
274
275 while (true)
276 {
277 for (i = 0; i < 8; i++)
278 {
279 dx = DirectionX[Dir];
280 dy = DirectionY[Dir];
281
282 x1 = x + dx;
283 y1 = y + dy;
284
285 if (x1 >= 0 && x1 < w && y1 >= 0 && y1 < h)
286 {
287 Index1 = Index + dx + dy * RowSize;
288 v = Data[Index1];
289 if ((v & 0x3fff) == Nr && (v & 0xc000) > 0)
290 {
291 x = x1;
292 y = y1;
293 Index = Index1;
294 Result.Add(P = new Point(x, y));
295 History.AddLast(new Rec(P, Dir));
296 Data[Index] &= 0x3fff;
297 break;
298 }
299 }
300
301 Dir = (Dir + 1) & 7;
302 }
303
304 if (i >= 8)
305 {
306 if (History.Last is null)
307 break;
308 else
309 {
310 Rec Rec = History.Last.Value;
311 History.RemoveLast();
312 x = Rec.P.X;
313 y = Rec.P.Y;
314 Dir = Rec.Dir;
315 Index = this.StartIndex(x, y);
316 }
317 }
318 }
319
320 return Result.ToArray();
321 }
322
323 private static readonly int[] DirectionX = new int[] { 1, 1, 0, -1, -1, -1, 0, 1 };
324 private static readonly int[] DirectionY = new int[] { 0, -1, -1, -1, 0, 1, 1, 1 };
325
326 private class Rec
327 {
328 public Rec(Point P, int Dir)
329 {
330 this.P = P;
331 this.Dir = Dir;
332 }
333
334 public Point P;
335 public int Dir;
336 }
337
341 public ObjectInformation[] Objects => this.objects;
342
349 public IMatrix Extract(params ushort[] Nrs)
350 {
351 return this.Extract(Nrs, this.image);
352 }
353
361 public IMatrix Extract(ushort[] Nrs, IMatrix Source)
362 {
363 if (Source.Width != this.Width || Source.Height != this.Height)
364 throw new ArgumentOutOfRangeException(nameof(Source));
365
366 ObjectInformation[] Infos = this.GetInfo(Nrs);
367
368 if (Source is Matrix<float> M)
369 return this.Extract<float>(Nrs, M, Infos, float.MinValue);
370 else if (Source is Matrix<int> M2)
371 return this.Extract<int>(Nrs, M2, Infos, int.MinValue);
372 else if (Source is Matrix<uint> M3)
373 return this.Extract<uint>(Nrs, M3, Infos, 0);
374 else if (Source is Matrix<byte> M4)
375 return this.Extract<byte>(Nrs, M4, Infos, 0);
376 else
377 throw new InvalidOperationException("Underlying image type not supported.");
378 }
379
380 private ObjectInformation[] GetInfo(ushort[] Nrs)
381 {
382 int i, c = Nrs.Length;
383 ObjectInformation[] Infos = new ObjectInformation[c];
384
385 for (i = 0; i < c; i++)
386 {
387 if (!this.objectsById.TryGetValue(Nrs[i], out ObjectInformation Info))
388 throw new ArgumentOutOfRangeException(nameof(Nrs));
389
390 Infos[i] = Info;
391 }
392
393 return Infos;
394 }
395
403 public Matrix<T> Extract<T>(ushort[] Nrs, Matrix<T> Source)
404 where T : struct
405 {
406 if (Source.Width != this.Width || Source.Height != this.Height)
407 throw new ArgumentOutOfRangeException(nameof(Source));
408
409 ObjectInformation[] Infos = this.GetInfo(Nrs);
410
411 return this.Extract<T>(Nrs, Source, Infos, default);
412 }
413
414 private Matrix<T> Extract<T>(ushort[] Nrs, Matrix<T> Image, ObjectInformation[] Objects, T BackgroundValue)
415 where T : struct
416 {
417 int x, y, c = Nrs.Length;
418 if (c != Objects.Length)
419 throw new ArgumentException("Array size mismatch.", nameof(Objects));
420
421 if (c == 0)
422 return new Matrix<T>(1, 1);
423
424 int SrcX1 = Objects[0].MinX;
425 int SrcY1 = Objects[0].MinY;
426 int SrcX2 = Objects[0].MaxX;
427 int SrcY2 = Objects[0].MaxY;
428 y = Objects[0].Nr;
429
430 for (x = 1; x < c; x++)
431 {
432 ObjectInformation Info = Objects[x];
433
434 if (Info.MinX < SrcX1)
435 SrcX1 = Info.MinX;
436
437 if (Info.MaxX > SrcX2)
438 SrcX2 = Info.MaxX;
439
440 if (Info.MinY < SrcY1)
441 SrcY1 = Info.MinY;
442
443 if (Info.MaxY > SrcY2)
444 SrcY2 = Info.MaxY;
445
446 if (Info.Nr > y)
447 y = Info.Nr;
448 }
449
450 bool[] Included = new bool[y + 2];
451 for (x = 0; x < c; x++)
452 Included[Objects[x].Nr + 1] = true;
453
454 c = y + 2;
455
456 int w = SrcX2 - SrcX1 + 1;
457 int h = SrcY2 - SrcY1 + 1;
458 int SrcIndex = Image.StartIndex(SrcX1, SrcY1);
459 int SrcSkip = Image.Skip + Image.Width - w;
460 int MaskIndex = this.StartIndex(SrcX1, SrcY1);
461 int MaskSkip = Image.Width - w;
462 ushort i;
463 Matrix<T> Result = new Matrix<T>(w, h);
464 ushort[] Mask = this.Data;
465 T[] Src = Image.Data;
466 T[] Dest = Result.Data;
467 int DestIndex = 0;
468
469 for (y = SrcY1; y <= SrcY2; y++, SrcIndex += SrcSkip, MaskIndex += MaskSkip)
470 {
471 for (x = SrcX1; x <= SrcX2; x++, SrcIndex++)
472 {
473 i = Mask[MaskIndex++];
474 i &= 0x3fff;
475 Dest[DestIndex++] = i < c && Included[i] ? Src[SrcIndex] : BackgroundValue;
476 }
477 }
478
479 return Result;
480 }
481 }
482}
Implements a Matrix, basic component for computations in Image Processing and Computer Vision.
Definition: Matrix.cs:12
int Height
Height of matrix (number of rows)
Definition: Matrix.cs:136
T[] Data
Underlying data on which the matrix is defined.
Definition: Matrix.cs:114
int Width
Width of matrix (number of columns)
Definition: Matrix.cs:120
int RowSize
Number of elements per row in underlying data array.
Definition: Matrix.cs:218
int Skip
Number of elements to skip from the right edge in the underlying data to the left edge of the new row...
Definition: Matrix.cs:233
int StartIndex(int X, int Y)
Gets the start index of a point in the image.
Definition: Matrix.cs:253
int Start
Start offset of matrix in underlying data.
Definition: Matrix.cs:228
Contains information about an object.
int MaxX
Largest X-coordinate of bounding box
int MinY
Smallest Y-coordinate of bounding box
ushort Nr
Object number in image
int MaxY
Largest Y-coordinate of bounding box
int MinX
Smallest X-coordinate of bounding box
Contains an object map of contents in an image.
Definition: ObjectMap.cs:11
ObjectMap(Matrix< float > M, float Threshold)
Contains an object map of contents in an image.
Definition: ObjectMap.cs:21
int NrObjects
Number of objects in map.
Definition: ObjectMap.cs:241
Matrix< T > Extract< T >(ushort[] Nrs, Matrix< T > Source)
Extracts one or more objects in the form of image from the underlying image. Only pixels pertaining t...
Definition: ObjectMap.cs:403
ObjectInformation[] Objects
Objects found in map.
Definition: ObjectMap.cs:341
IMatrix Extract(params ushort[] Nrs)
Extracts one or more objects in the form of image from the underlying image. Only pixels pertaining t...
Definition: ObjectMap.cs:349
IMatrix Image
Underlying image.
Definition: ObjectMap.cs:236
ObjectMap(Matrix< int > M, int Threshold)
Contains an object map of contents in an image.
Definition: ObjectMap.cs:130
IMatrix Extract(ushort[] Nrs, IMatrix Source)
Extracts one or more objects in the form of image from the underlying image. Only pixels pertaining t...
Definition: ObjectMap.cs:361
Interface for matrices.
Definition: IMatrix.cs:9
int Height
Height of matrix (number of rows)
Definition: IMatrix.cs:23
int StartIndex(int X, int Y)
Gets the start index of a point in the image.
int Width
Width of matrix (number of columns)
Definition: IMatrix.cs:18
Represents a point in an image.
Definition: Point.cs:7