DepthImage.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using MathNet.Numerics.LinearAlgebra.Single;
  7. using System.Drawing;
  8. using Emgu.CV;
  9. using Emgu.CV.Structure;
  10. namespace bbiwarg.Images
  11. {
  12. /**
  13. * Represents an depth image where the depth is given in distance to the camera in millimeters.
  14. */
  15. class DepthImage
  16. {
  17. private int width, height;
  18. private Image<Gray, short> image;
  19. private int[] histogram;
  20. public DepthImage(int width, int height, short[] data)
  21. {
  22. this.width = width;
  23. this.height = height;
  24. image = new Image<Gray, short>(width, height);
  25. for (int i = 0; i < data.Length; ++i)
  26. setDepth(i % width, i / width, data[i]);
  27. }
  28. public int getWidth()
  29. {
  30. return width;
  31. }
  32. public int getHeight()
  33. {
  34. return height;
  35. }
  36. public short getDepth(int x, int y)
  37. {
  38. return image.Data[y, x, 0];
  39. }
  40. private void setDepth(int x, int y, short depth)
  41. {
  42. image.Data[y, x, 0] = depth;
  43. }
  44. public void filterMedian(int filterSize)
  45. {
  46. image = image.SmoothMedian(filterSize);
  47. }
  48. public void thresholdDepth(int min, int max)
  49. {
  50. image = image.ThresholdToZero(new Gray(min));
  51. image = image.ThresholdTrunc(new Gray(max));
  52. for (int x = 0; x < width; ++x)
  53. {
  54. for (int y = 0; y < height; ++y)
  55. {
  56. if (getDepth(x, y) == 0)
  57. setDepth(x, y, (short) max);
  58. }
  59. }
  60. }
  61. public int[] getSmoothedHistogram()
  62. {
  63. Int16 minDepth = getMinDepth();
  64. Int16 maxDepth = getMaxDepth();
  65. histogram = new int[maxDepth - minDepth];
  66. for (int x = 0; x < width; ++x)
  67. {
  68. for (int y = 0; y < height; ++y)
  69. {
  70. int depth = getDepth(x, y);
  71. if (depth != maxDepth)
  72. histogram[depth - minDepth]++;
  73. }
  74. }
  75. smoothHistogram();
  76. return histogram;
  77. }
  78. private void smoothHistogram()
  79. {
  80. histogram[0] = (histogram[0] + histogram[1]) / 2;
  81. histogram[histogram.Length - 1] = (histogram[histogram.Length - 2] + histogram[histogram.Length - 1]) / 2;
  82. for (int i = 1; i < histogram.Length - 1; ++i)
  83. {
  84. histogram[i] = (histogram[i - 1] + histogram[i] + histogram[i + 1]) / 3;
  85. }
  86. }
  87. public Int16[] getSegmentationDepth()
  88. {
  89. //get first peak
  90. Int16 firstMaxIndex = 0;
  91. for (Int16 i = 0; i < histogram.Length; i++) {
  92. if (histogram[i] > histogram[firstMaxIndex]) {
  93. firstMaxIndex = i;
  94. }
  95. }
  96. // get second peak
  97. Int16 minDistance = 20; // mm
  98. Int16 secondMaxIndex = 0;
  99. for (Int16 i = 0; i < histogram.Length; i++) {
  100. if (Math.Abs(firstMaxIndex - i) > minDistance && histogram[i] > histogram[secondMaxIndex]) {
  101. secondMaxIndex = i;
  102. }
  103. }
  104. Int16 minDepth = getMinDepth();
  105. Int16[] result = new Int16[3];
  106. result[0] = (Int16) (Math.Min(firstMaxIndex, secondMaxIndex) + minDepth);
  107. result[1] = (Int16) ((firstMaxIndex + secondMaxIndex) / 2 + minDepth);
  108. result[2] = (Int16) (Math.Max(firstMaxIndex, secondMaxIndex) + minDepth);
  109. return result;
  110. }
  111. public Int16 getPeakDepth()
  112. {
  113. Int16 minDepth = getMinDepth();
  114. Int16 peak = -1;
  115. int maxValue = 0;
  116. for (int i = 0; i < histogram.Length; ++i)
  117. {
  118. if (histogram[i] > maxValue)
  119. {
  120. maxValue = histogram[i];
  121. peak = (Int16) (i + minDepth);
  122. }
  123. }
  124. return peak;
  125. }
  126. public Int16 getMinDepth()
  127. {
  128. Int16 minDepth = Int16.MaxValue;
  129. for (int x = 0; x < width; ++x)
  130. {
  131. for (int y = 0; y < height; ++y)
  132. {
  133. Int16 depth = getDepth(x, y);
  134. if (depth < minDepth)
  135. minDepth = depth;
  136. }
  137. }
  138. return minDepth;
  139. }
  140. public Int16 getMaxDepth()
  141. {
  142. Int16 maxDepth = Int16.MinValue;
  143. for (int x = 0; x < width; ++x)
  144. {
  145. for (int y = 0; y < height; ++y)
  146. {
  147. Int16 depth = getDepth(x, y);
  148. if (depth > maxDepth)
  149. maxDepth = depth;
  150. }
  151. }
  152. return maxDepth;
  153. }
  154. public void floodFill(int x, int y, int val)
  155. {
  156. Image<Gray, Byte> tmp = image.Convert<Byte>(delegate(short s) { return (byte) ((int) s * Byte.MaxValue / 2000); });
  157. Emgu.CV.Structure.MCvConnectedComp comp = new MCvConnectedComp();
  158. Emgu.CV.CvInvoke.cvFloodFill(tmp.Ptr, new Point(x, y), new MCvScalar(val), new MCvScalar(30), new MCvScalar(30), out comp, 0, IntPtr.Zero);
  159. for (int i = 0; i < width; ++i)
  160. {
  161. for (int j = 0; j < height; ++j)
  162. {
  163. if (tmp.Data[j, i, 0] == 255)
  164. setDepth(i, j, 2000);
  165. else
  166. setDepth(i, j, 0);
  167. }
  168. }
  169. }
  170. }
  171. }