image-js 0.35.1 → 0.35.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/index.d.ts +99 -35
  2. package/lib/browser/environment.js +0 -6
  3. package/lib/browser/worker/extend.js +0 -3
  4. package/lib/browser/worker/process/background.js +0 -12
  5. package/lib/browser/worker/worker.js +0 -17
  6. package/lib/image/Image.js +18 -51
  7. package/lib/image/compute/colorHistogram.js +0 -8
  8. package/lib/image/compute/countAlphaPixels.js +0 -3
  9. package/lib/image/compute/extendedPoints.js +2 -7
  10. package/lib/image/compute/histogram.js +6 -25
  11. package/lib/image/compute/localMaxima.js +2 -10
  12. package/lib/image/compute/max.js +0 -5
  13. package/lib/image/compute/mean.js +0 -4
  14. package/lib/image/compute/median.js +0 -4
  15. package/lib/image/compute/min.js +0 -5
  16. package/lib/image/compute/minimalBoundingRectangle.js +5 -18
  17. package/lib/image/compute/moment.js +0 -3
  18. package/lib/image/compute/monotoneChainConvexHull.js +0 -3
  19. package/lib/image/compute/points.js +0 -3
  20. package/lib/image/compute/relativePosition.js +2 -8
  21. package/lib/image/compute/sum.js +0 -5
  22. package/lib/image/core/bitMethods.js +0 -11
  23. package/lib/image/core/checkProcessable.js +0 -13
  24. package/lib/image/core/environment.js +0 -8
  25. package/lib/image/core/export.js +0 -38
  26. package/lib/image/core/extend.js +0 -13
  27. package/lib/image/core/getRGBAData.js +0 -15
  28. package/lib/image/core/kind.js +4 -28
  29. package/lib/image/core/kindNames.js +1 -0
  30. package/lib/image/core/load.js +1 -53
  31. package/lib/image/core/mediaTypes.js +0 -2
  32. package/lib/image/core/valueMethods.js +0 -13
  33. package/lib/image/extend.js +7 -83
  34. package/lib/image/filter/abs.js +0 -3
  35. package/lib/image/filter/add.js +2 -8
  36. package/lib/image/filter/background.js +0 -9
  37. package/lib/image/filter/blurFilter.js +0 -6
  38. package/lib/image/filter/divide.js +0 -8
  39. package/lib/image/filter/flipX.js +0 -5
  40. package/lib/image/filter/flipY.js +0 -4
  41. package/lib/image/filter/gaussianFilter.js +0 -5
  42. package/lib/image/filter/gradientFilter.js +0 -10
  43. package/lib/image/filter/hypotenuse.js +0 -13
  44. package/lib/image/filter/invert.js +0 -9
  45. package/lib/image/filter/level.js +1 -19
  46. package/lib/image/filter/medianFilter.js +0 -15
  47. package/lib/image/filter/multiply.js +0 -10
  48. package/lib/image/filter/scharrFilter.js +0 -4
  49. package/lib/image/filter/sobelFilter.js +0 -4
  50. package/lib/image/filter/subtract.js +0 -8
  51. package/lib/image/filter/subtractImage.js +0 -10
  52. package/lib/image/internal/checks.js +1 -9
  53. package/lib/image/internal/clamp.js +0 -1
  54. package/lib/image/internal/copy.js +0 -2
  55. package/lib/image/internal/copyAlphaChannel.js +0 -1
  56. package/lib/image/internal/getImageParameters.js +0 -1
  57. package/lib/image/internal/getOutputImage.js +1 -13
  58. package/lib/image/model/model.js +1 -1
  59. package/lib/image/morphology/blackHat.js +0 -5
  60. package/lib/image/morphology/close.js +0 -5
  61. package/lib/image/morphology/dilate.js +0 -40
  62. package/lib/image/morphology/erode.js +0 -40
  63. package/lib/image/morphology/morphologicalGradient.js +0 -5
  64. package/lib/image/morphology/open.js +0 -5
  65. package/lib/image/morphology/topHat.js +0 -5
  66. package/lib/image/operator/cannyEdge.js +0 -3
  67. package/lib/image/operator/convolution.js +9 -34
  68. package/lib/image/operator/convolutionSeparable.js +0 -10
  69. package/lib/image/operator/extract.js +4 -13
  70. package/lib/image/operator/floodFill.js +2 -15
  71. package/lib/image/operator/getSeparatedKernel.js +0 -2
  72. package/lib/image/operator/paintLabels.js +8 -19
  73. package/lib/image/operator/paintMasks.js +2 -12
  74. package/lib/image/operator/paintPoints.js +0 -9
  75. package/lib/image/operator/paintPolygon.js +1 -15
  76. package/lib/image/operator/paintPolygons.js +2 -6
  77. package/lib/image/operator/paintPolyline.js +0 -7
  78. package/lib/image/operator/paintPolylines.js +1 -5
  79. package/lib/image/roi/Roi.js +27 -207
  80. package/lib/image/roi/RoiLayer.js +1 -22
  81. package/lib/image/roi/RoiMap.js +5 -38
  82. package/lib/image/roi/creator/fromMask.js +4 -22
  83. package/lib/image/roi/creator/fromMaskConnectedComponentLabelingAlgorithm.js +2 -20
  84. package/lib/image/roi/creator/fromMaxima.js +10 -43
  85. package/lib/image/roi/creator/fromPoints.js +2 -10
  86. package/lib/image/roi/creator/fromWaterShed.js +6 -17
  87. package/lib/image/roi/feretDiameters.js +9 -21
  88. package/lib/image/roi/manager.js +30 -119
  89. package/lib/image/roi/util/commonBorderLength.js +5 -16
  90. package/lib/image/roi/util/mergeRoi.js +2 -21
  91. package/lib/image/transform/cmyk.js +0 -9
  92. package/lib/image/transform/colorDepth.js +0 -12
  93. package/lib/image/transform/crop.js +0 -20
  94. package/lib/image/transform/cropAlpha.js +0 -11
  95. package/lib/image/transform/grey.js +0 -16
  96. package/lib/image/transform/greyAlgorithms.js +1 -24
  97. package/lib/image/transform/hsl.js +0 -16
  98. package/lib/image/transform/hsv.js +0 -15
  99. package/lib/image/transform/insert.js +0 -6
  100. package/lib/image/transform/mask/huang.js +3 -18
  101. package/lib/image/transform/mask/intermodes.js +3 -14
  102. package/lib/image/transform/mask/isodata.js +0 -14
  103. package/lib/image/transform/mask/li.js +12 -42
  104. package/lib/image/transform/mask/mask.js +1 -13
  105. package/lib/image/transform/mask/maxEntropy.js +8 -25
  106. package/lib/image/transform/mask/mean.js +1 -3
  107. package/lib/image/transform/mask/minError.js +10 -21
  108. package/lib/image/transform/mask/minimum.js +0 -20
  109. package/lib/image/transform/mask/moments.js +4 -17
  110. package/lib/image/transform/mask/otsu.js +1 -7
  111. package/lib/image/transform/mask/percentile.js +0 -8
  112. package/lib/image/transform/mask/renyiEntropy.js +8 -34
  113. package/lib/image/transform/mask/shanbhag.js +8 -25
  114. package/lib/image/transform/mask/thresholdAlgorithms.js +1 -17
  115. package/lib/image/transform/mask/triangle.js +13 -29
  116. package/lib/image/transform/mask/yen.js +2 -14
  117. package/lib/image/transform/pad.js +0 -20
  118. package/lib/image/transform/resize/nearestNeighbor.js +0 -6
  119. package/lib/image/transform/resize/resize.js +0 -16
  120. package/lib/image/transform/rgba.js +0 -9
  121. package/lib/image/transform/rgba8.js +0 -3
  122. package/lib/image/transform/rotate.js +0 -29
  123. package/lib/image/transform/rotateFree.js +0 -31
  124. package/lib/image/transform/warping.js +2 -35
  125. package/lib/image/utility/combineChannels.js +0 -11
  126. package/lib/image/utility/getBestMatch.js +2 -13
  127. package/lib/image/utility/getChannel.js +0 -10
  128. package/lib/image/utility/getClosestCommonParent.js +6 -23
  129. package/lib/image/utility/getColumn.js +0 -4
  130. package/lib/image/utility/getIntersection.js +2 -18
  131. package/lib/image/utility/getMatrix.js +0 -7
  132. package/lib/image/utility/getPixelsArray.js +0 -5
  133. package/lib/image/utility/getPixelsGrid.js +0 -11
  134. package/lib/image/utility/getRow.js +0 -4
  135. package/lib/image/utility/getSimilarity.js +3 -17
  136. package/lib/image/utility/getThreshold.js +0 -4
  137. package/lib/image/utility/setBorder.js +0 -16
  138. package/lib/image/utility/setChannel.js +0 -6
  139. package/lib/image/utility/setMatrix.js +0 -6
  140. package/lib/image/utility/split.js +2 -15
  141. package/lib/index.js +0 -12
  142. package/lib/kernel/kernel.js +0 -3
  143. package/lib/kernel/laplacianOfGaussian.js +1 -7
  144. package/lib/node_modules/test/binary.js +0 -3
  145. package/lib/node_modules/test/oneRoi.js +0 -2
  146. package/lib/stack/Stack.js +2 -35
  147. package/lib/stack/compute/histogram.js +0 -4
  148. package/lib/stack/compute/histograms.js +0 -4
  149. package/lib/stack/compute/max.js +0 -3
  150. package/lib/stack/compute/median.js +0 -4
  151. package/lib/stack/compute/min.js +0 -3
  152. package/lib/stack/extend.js +1 -11
  153. package/lib/stack/transform/matchAndCrop.js +6 -19
  154. package/lib/stack/utility/averageImage.js +0 -9
  155. package/lib/stack/utility/maxImage.js +0 -7
  156. package/lib/stack/utility/minImage.js +0 -7
  157. package/lib/util/Shape.js +3 -40
  158. package/lib/util/base64.js +3 -14
  159. package/lib/util/channel.js +1 -35
  160. package/lib/util/color.js +1 -25
  161. package/lib/util/converter.js +1 -13
  162. package/lib/util/deepValue.js +0 -3
  163. package/lib/util/histogram.js +1 -12
  164. package/lib/util/kernel.js +2 -12
  165. package/lib/util/matrix.js +0 -13
  166. package/lib/util/points.js +12 -35
  167. package/lib/util/value.js +0 -7
  168. package/lib/util/zerosMatrix.js +0 -3
  169. package/package.json +2 -2
  170. package/src/image/operator/paintLabels.js +6 -6
  171. package/src/image/operator/paintPolygon.js +1 -1
  172. package/src/image/operator/paintPolygons.js +2 -2
  173. package/src/image/operator/paintPolylines.js +1 -1
@@ -4,29 +4,17 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _monotoneChainConvexHull = _interopRequireDefault(require("monotone-chain-convex-hull"));
9
-
10
8
  var _robustPointInPolygon = _interopRequireDefault(require("robust-point-in-polygon"));
11
-
12
9
  var _Shape = _interopRequireDefault(require("../../util/Shape"));
13
-
14
10
  var _points = require("../../util/points");
15
-
16
11
  var _Image = _interopRequireDefault(require("../Image"));
17
-
18
12
  var _minimalBoundingRectangle = _interopRequireDefault(require("../compute/minimalBoundingRectangle"));
19
-
20
13
  var KindNames = _interopRequireWildcard(require("../core/kindNames"));
21
-
22
14
  var _feretDiameters = _interopRequireDefault(require("./feretDiameters"));
23
-
24
15
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
25
-
26
16
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
27
-
28
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
-
30
18
  // Many measurements:
31
19
  // https://www.sympatec.com/en/particle-measurement/glossary/particle-shape/#
32
20
 
@@ -47,6 +35,7 @@ class Roi {
47
35
  this.surface = 0;
48
36
  this.computed = {};
49
37
  }
38
+
50
39
  /**
51
40
  * Returns a binary image (mask) for the corresponding ROI
52
41
  * @param {object} [options]
@@ -54,56 +43,43 @@ class Roi {
54
43
  * @param {string} [options.kind='normal'] - 'contour', 'box', 'filled', 'center', 'hull' or 'normal'
55
44
  * @return {Image} - Returns a mask (1 bit Image)
56
45
  */
57
-
58
-
59
46
  getMask(options = {}) {
60
47
  const {
61
48
  scale = 1,
62
49
  kind = ''
63
50
  } = options;
64
51
  let mask;
65
-
66
52
  switch (kind) {
67
53
  case 'contour':
68
54
  mask = this.contourMask;
69
55
  break;
70
-
71
56
  case 'box':
72
57
  mask = this.boxMask;
73
58
  break;
74
-
75
59
  case 'filled':
76
60
  mask = this.filledMask;
77
61
  break;
78
-
79
62
  case 'center':
80
63
  mask = this.centerMask;
81
64
  break;
82
-
83
65
  case 'mbr':
84
66
  mask = this.mbrFilledMask;
85
67
  break;
86
-
87
68
  case 'hull':
88
69
  mask = this.convexHullFilledMask;
89
70
  break;
90
-
91
71
  case 'hullContour':
92
72
  mask = this.convexHullMask;
93
73
  break;
94
-
95
74
  case 'mbrContour':
96
75
  mask = this.mbrMask;
97
76
  break;
98
-
99
77
  case 'feret':
100
78
  mask = this.feretMask;
101
79
  break;
102
-
103
80
  default:
104
81
  mask = this.mask;
105
82
  }
106
-
107
83
  if (scale < 1) {
108
84
  // by reassigning the mask we loose the parent and therefore the position
109
85
  // we will have to force it back
@@ -114,34 +90,28 @@ class Roi {
114
90
  mask.position[0] += this.minX;
115
91
  mask.position[1] += this.minY;
116
92
  }
117
-
118
93
  return mask;
119
94
  }
120
-
121
95
  get mean() {
122
- throw new Error('Roi mean not implemented yet'); // return [this.meanX,this.meanY];
96
+ throw new Error('Roi mean not implemented yet');
97
+ // return [this.meanX,this.meanY];
123
98
  }
124
99
 
125
100
  get center() {
126
101
  if (!this.computed.center) {
127
102
  this.computed.center = [this.width / 2 >> 0, this.height / 2 >> 0];
128
103
  }
129
-
130
104
  return this.computed.center;
131
105
  }
132
-
133
106
  get ratio() {
134
107
  return this.width / this.height;
135
108
  }
136
-
137
109
  get width() {
138
110
  return this.maxX - this.minX + 1;
139
111
  }
140
-
141
112
  get height() {
142
113
  return this.maxY - this.minY + 1;
143
114
  }
144
-
145
115
  _computExternalIDs() {
146
116
  // take all the borders and remove the internal one ...
147
117
  let borders = this.borderIDs;
@@ -149,7 +119,6 @@ class Roi {
149
119
  this.computed.externalIDs = [];
150
120
  this.computed.externalLengths = [];
151
121
  let internals = this.internalIDs;
152
-
153
122
  for (let i = 0; i < borders.length; i++) {
154
123
  if (!internals.includes(borders[i])) {
155
124
  this.computed.externalIDs.push(borders[i]);
@@ -157,62 +126,50 @@ class Roi {
157
126
  }
158
127
  }
159
128
  }
160
-
161
129
  get externalIDs() {
162
130
  if (this.computed.externalIDs) {
163
131
  return this.computed.externalIDs;
164
132
  }
165
-
166
133
  this._computExternalIDs();
167
-
168
134
  return this.computed.externalIDs;
169
135
  }
170
-
171
136
  get externalLengths() {
172
137
  if (this.computed.externalLengths) {
173
138
  return this.computed.externalLengths;
174
139
  }
175
-
176
140
  this._computExternalIDs();
177
-
178
141
  return this.computed.externalLengths;
179
142
  }
180
-
181
143
  _computeBorderIDs() {
182
144
  let borders = getBorders(this);
183
145
  this.computed.borderIDs = borders.ids;
184
146
  this.computed.borderLengths = borders.lengths;
185
147
  }
148
+
186
149
  /**
187
150
  Retrieve all the IDs (array of number) of the regions that are in contact with this
188
151
  specific region. It may be external or internal
189
152
  */
190
-
191
-
192
153
  get borderIDs() {
193
154
  if (this.computed.borderIDs) {
194
155
  return this.computed.borderIDs;
195
156
  }
196
-
197
157
  this._computeBorderIDs();
198
-
199
158
  return this.computed.borderIDs;
200
159
  }
160
+
201
161
  /**
202
162
  Retrieve all the length (array of number) of the contacts with this
203
163
  specific region. It may be external or internal
204
164
  */
205
-
206
-
207
165
  get borderLengths() {
208
166
  if (this.computed.borderLengths) {
209
167
  return this.computed.borderLengths;
210
168
  }
211
-
212
169
  this._computeBorderIDs();
213
-
214
170
  return this.computed.borderLengths;
215
171
  }
172
+
216
173
  /**
217
174
  Retrieve all the IDs or the Roi touching the box surrouding the region
218
175
  It should really be an array to solve complex cases related to border effect
@@ -233,66 +190,56 @@ class Roi {
233
190
  The cross will be surrouned by 4 differents zones
234
191
  However in most of the cases it will be an array of one element
235
192
  */
236
-
237
-
238
193
  get boxIDs() {
239
194
  if (!this.computed.boxIDs) {
240
195
  this.computed.boxIDs = getBoxIDs(this);
241
196
  }
242
-
243
197
  return this.computed.boxIDs;
244
198
  }
245
-
246
199
  get internalIDs() {
247
200
  if (!this.computed.internalIDs) {
248
201
  this.computed.internalIDs = getInternalIDs(this);
249
202
  }
250
-
251
203
  return this.computed.internalIDs;
252
204
  }
205
+
253
206
  /**
254
207
  Number of pixels of the Roi that touch the rectangle
255
208
  This is useful for the calculation of the border
256
209
  because we will ignore those special pixels of the rectangle
257
210
  border that don't have neighbours all around them.
258
211
  */
259
-
260
-
261
212
  get box() {
262
213
  // points of the Roi that touch the rectangular shape
263
214
  if (!this.computed.box) {
264
215
  this.computed.box = getBox(this);
265
216
  }
266
-
267
217
  return this.computed.box;
268
218
  }
219
+
269
220
  /**
270
221
  Calculates the number of pixels that are in the external border of the Roi
271
222
  Contour are all the pixels that touch an external "zone".
272
223
  All the pixels that touch the box are part of the border and
273
224
  are calculated in the getBoxPixels procedure
274
225
  */
275
-
276
-
277
226
  get external() {
278
227
  if (!this.computed.external) {
279
228
  this.computed.external = getExternal(this);
280
229
  }
281
-
282
230
  return this.computed.external;
283
231
  }
232
+
284
233
  /**
285
234
  Calculates information about holes
286
235
  */
287
-
288
-
289
236
  get holesInfo() {
290
237
  if (!this.computed.holesInfo) {
291
238
  this.computed.holesInfo = getHolesInfo(this);
292
239
  }
293
-
294
240
  return this.computed.holesInfo;
295
241
  }
242
+
296
243
  /**
297
244
  Calculates the number of pixels that are involved in border
298
245
  Border are all the pixels that touch another "zone". It could be external
@@ -300,20 +247,16 @@ class Roi {
300
247
  All the pixels that touch the box are part of the border and
301
248
  are calculated in the getBoxPixels procedure
302
249
  */
303
-
304
-
305
250
  get border() {
306
251
  if (!this.computed.border) {
307
252
  this.computed.border = getBorder(this);
308
253
  }
309
-
310
254
  return this.computed.border;
311
255
  }
256
+
312
257
  /**
313
258
  Returns a binary image (mask) containing only the border of the mask
314
259
  */
315
-
316
-
317
260
  get contourMask() {
318
261
  if (!this.computed.contourMask) {
319
262
  let img = new _Image.default(this.width, this.height, {
@@ -321,7 +264,6 @@ class Roi {
321
264
  position: [this.minX, this.minY],
322
265
  parent: this.map.parent
323
266
  });
324
-
325
267
  for (let x = 0; x < this.width; x++) {
326
268
  for (let y = 0; y < this.height; y++) {
327
269
  if (this.map.data[x + this.minX + (y + this.minY) * this.map.width] === this.id) {
@@ -336,13 +278,10 @@ class Roi {
336
278
  }
337
279
  }
338
280
  }
339
-
340
281
  this.computed.contourMask = img;
341
282
  }
342
-
343
283
  return this.computed.contourMask;
344
284
  }
345
-
346
285
  get boxMask() {
347
286
  if (!this.computed.boxMask) {
348
287
  let img = new _Image.default(this.width, this.height, {
@@ -350,27 +289,22 @@ class Roi {
350
289
  position: [this.minX, this.minY],
351
290
  parent: this.map.parent
352
291
  });
353
-
354
292
  for (let x = 0; x < this.width; x++) {
355
293
  img.setBitXY(x, 0);
356
294
  img.setBitXY(x, this.height - 1);
357
295
  }
358
-
359
296
  for (let y = 0; y < this.height; y++) {
360
297
  img.setBitXY(0, y);
361
298
  img.setBitXY(this.width - 1, y);
362
299
  }
363
-
364
300
  this.computed.boxMask = img;
365
301
  }
366
-
367
302
  return this.computed.boxMask;
368
303
  }
304
+
369
305
  /**
370
306
  Returns a binary image containing the mask
371
307
  */
372
-
373
-
374
308
  get mask() {
375
309
  if (!this.computed.mask) {
376
310
  let img = new _Image.default(this.width, this.height, {
@@ -378,7 +312,6 @@ class Roi {
378
312
  position: [this.minX, this.minY],
379
313
  parent: this.map.parent
380
314
  });
381
-
382
315
  for (let x = 0; x < this.width; x++) {
383
316
  for (let y = 0; y < this.height; y++) {
384
317
  if (this.map.data[x + this.minX + (y + this.minY) * this.map.width] === this.id) {
@@ -386,13 +319,10 @@ class Roi {
386
319
  }
387
320
  }
388
321
  }
389
-
390
322
  this.computed.mask = img;
391
323
  }
392
-
393
324
  return this.computed.mask;
394
325
  }
395
-
396
326
  get filledMask() {
397
327
  if (!this.computed.filledMask) {
398
328
  let img = new _Image.default(this.width, this.height, {
@@ -400,24 +330,19 @@ class Roi {
400
330
  position: [this.minX, this.minY],
401
331
  parent: this.map.parent
402
332
  });
403
-
404
333
  for (let x = 0; x < this.width; x++) {
405
334
  for (let y = 0; y < this.height; y++) {
406
335
  let target = x + this.minX + (y + this.minY) * this.map.width;
407
-
408
336
  if (this.internalIDs.includes(this.map.data[target])) {
409
337
  img.setBitXY(x, y);
410
338
  } // by default a pixel is to 0 so no problems, it will be transparent
411
-
412
339
  }
413
340
  }
414
341
 
415
342
  this.computed.filledMask = img;
416
343
  }
417
-
418
344
  return this.computed.filledMask;
419
345
  }
420
-
421
346
  get centerMask() {
422
347
  if (!this.computed.centerMask) {
423
348
  let img = new _Shape.default({
@@ -427,13 +352,12 @@ class Roi {
427
352
  img.position = [this.minX + this.center[0] - 1, this.minY + this.center[1] - 1];
428
353
  this.computed.centerMask = img;
429
354
  }
430
-
431
355
  return this.computed.centerMask;
432
356
  }
433
-
434
357
  get convexHull() {
435
358
  if (!this.computed.convexHull) {
436
- const calculationPoints = []; // slow approach, we check all the points
359
+ const calculationPoints = [];
360
+ // slow approach, we check all the points
437
361
  // for each point we take the 4 corners !!!!
438
362
 
439
363
  for (let x = 0; x < this.width; x++) {
@@ -456,7 +380,6 @@ class Roi {
456
380
  }
457
381
  }
458
382
  }
459
-
460
383
  const convexHull = (0, _monotoneChainConvexHull.default)(calculationPoints);
461
384
  this.computed.convexHull = {
462
385
  polyline: convexHull,
@@ -464,10 +387,8 @@ class Roi {
464
387
  perimeter: (0, _points.perimeter)(convexHull)
465
388
  };
466
389
  }
467
-
468
390
  return this.computed.convexHull;
469
391
  }
470
-
471
392
  get convexHullMask() {
472
393
  if (!this.computed.convexHullMask) {
473
394
  const convexHull = this.convexHull;
@@ -481,10 +402,8 @@ class Roi {
481
402
  });
482
403
  this.computed.convexHullMask = img;
483
404
  }
484
-
485
405
  return this.computed.convexHullMask;
486
406
  }
487
-
488
407
  get convexHullFilledMask() {
489
408
  if (!this.computed.convexHullFilledMask) {
490
409
  const convexHull = this.convexHull;
@@ -493,7 +412,6 @@ class Roi {
493
412
  position: [this.minX, this.minY],
494
413
  parent: this.map.parent
495
414
  });
496
-
497
415
  for (let x = 0; x < this.width; x++) {
498
416
  for (let y = 0; y < this.height; y++) {
499
417
  if ((0, _robustPointInPolygon.default)(convexHull.polyline, [x, y]) !== 1) {
@@ -501,19 +419,15 @@ class Roi {
501
419
  }
502
420
  }
503
421
  }
504
-
505
422
  this.computed.convexHullFilledMask = img;
506
423
  }
507
-
508
424
  return this.computed.convexHullFilledMask;
509
425
  }
510
-
511
426
  get mbr() {
512
427
  if (!this.computed.mbr) {
513
428
  let mbr = (0, _minimalBoundingRectangle.default)({
514
429
  originalPoints: this.convexHull.polyline
515
430
  });
516
-
517
431
  if (mbr.length === 0) {
518
432
  this.computed.mbr = {
519
433
  width: 0,
@@ -539,70 +453,58 @@ class Roi {
539
453
  };
540
454
  }
541
455
  }
542
-
543
456
  return this.computed.mbr;
544
457
  }
545
-
546
458
  get fillRatio() {
547
459
  return this.surface / (this.surface + this.holesInfo.surface);
548
460
  }
549
-
550
461
  get feretDiameters() {
551
462
  if (!this.computed.feretDiameters) {
552
463
  this.computed.feretDiameters = (0, _feretDiameters.default)({
553
464
  originalPoints: this.convexHull.polyline
554
465
  });
555
466
  }
556
-
557
467
  return this.computed.feretDiameters;
558
468
  }
469
+
559
470
  /**
560
471
  * Diameter of a circle of equal projection area
561
472
  */
562
-
563
-
564
473
  get eqpc() {
565
474
  if (!this.computed.eqpc) {
566
475
  this.computed.eqpc = 2 * Math.sqrt(this.surface / Math.PI);
567
476
  }
568
-
569
477
  return this.computed.eqpc;
570
478
  }
479
+
571
480
  /**
572
481
  * Get the category in which each external pixel belongs
573
482
  */
574
-
575
-
576
483
  get perimeterInfo() {
577
484
  if (!this.computed.perimeterInfo) {
578
485
  this.computed.perimeterInfo = getPerimeterInfo(this);
579
486
  }
580
-
581
487
  return this.computed.perimeterInfo;
582
488
  }
489
+
583
490
  /**
584
491
  * Return the perimeter of the ROI
585
492
  */
586
-
587
-
588
493
  get perimeter() {
589
494
  let info = this.perimeterInfo;
590
495
  let delta = 2 - Math.sqrt(2);
591
496
  return info.one + info.two * 2 + info.three * 3 + info.four * 4 - delta * (info.two + info.three * 2 + info.four);
592
497
  }
498
+
593
499
  /**
594
500
  * Diameter of a circle of equal perimeter
595
501
  */
596
-
597
-
598
502
  get ped() {
599
503
  if (!this.computed.ped) {
600
504
  this.computed.ped = this.perimeter / Math.PI;
601
505
  }
602
-
603
506
  return this.computed.ped;
604
507
  }
605
-
606
508
  get feretMask() {
607
509
  if (!this.computed.feretMask) {
608
510
  const image = new _Image.default(this.width + 1, this.height + 1, {
@@ -614,14 +516,11 @@ class Roi {
614
516
  image.paintPolyline(this.feretDiameters.maxLine);
615
517
  this.computed.feretMask = image;
616
518
  }
617
-
618
519
  return this.computed.feretMask;
619
520
  }
620
-
621
521
  get mbrMask() {
622
522
  if (!this.computed.mbrMask) {
623
523
  let rectangle = (0, _points.round)(this.mbr.rectangle);
624
-
625
524
  if (rectangle.length > 0) {
626
525
  // the problem is that the rectangle may be outside the roi
627
526
  const minMax = (0, _points.minMax)(rectangle);
@@ -643,10 +542,8 @@ class Roi {
643
542
  });
644
543
  }
645
544
  }
646
-
647
545
  return this.computed.mbrMask;
648
546
  }
649
-
650
547
  get mbrFilledMask() {
651
548
  if (!this.computed.mbrFilledMask) {
652
549
  const img = new _Image.default(this.width, this.height, {
@@ -655,7 +552,6 @@ class Roi {
655
552
  parent: this.map.parent
656
553
  });
657
554
  const mbr = this.mask.minimalBoundingRectangle();
658
-
659
555
  for (let x = 0; x < this.width; x++) {
660
556
  for (let y = 0; y < this.height; y++) {
661
557
  if ((0, _robustPointInPolygon.default)(mbr, [x, y]) !== 1) {
@@ -663,92 +559,72 @@ class Roi {
663
559
  }
664
560
  }
665
561
  }
666
-
667
562
  this.computed.mbrFilledMask = img;
668
563
  }
669
-
670
564
  return this.computed.mbrFilledMask;
671
565
  }
672
-
673
566
  get points() {
674
567
  if (!this.computed.points) {
675
568
  let points = [];
676
-
677
569
  for (let y = 0; y < this.height; y++) {
678
570
  for (let x = 0; x < this.width; x++) {
679
571
  let target = (y + this.minY) * this.map.width + x + this.minX;
680
-
681
572
  if (this.map.data[target] === this.id) {
682
573
  points.push([x, y]);
683
574
  }
684
575
  }
685
576
  }
686
-
687
577
  this.computed.points = points;
688
578
  }
689
-
690
579
  return this.computed.points;
691
580
  }
692
-
693
581
  get maxLengthPoints() {
694
582
  if (!this.computed.maxLengthPoints) {
695
583
  let maxLength = 0;
696
584
  let maxLengthPoints;
697
585
  const points = this.points;
698
-
699
586
  for (let i = 0; i < points.length; i++) {
700
587
  for (let j = i + 1; j < points.length; j++) {
701
588
  let currentML = Math.pow(points[i][0] - points[j][0], 2) + Math.pow(points[i][1] - points[j][1], 2);
702
-
703
589
  if (currentML >= maxLength) {
704
590
  maxLength = currentML;
705
591
  maxLengthPoints = [points[i], points[j]];
706
592
  }
707
593
  }
708
594
  }
709
-
710
595
  this.computed.maxLengthPoints = maxLengthPoints;
711
596
  }
712
-
713
597
  return this.computed.maxLengthPoints;
714
598
  }
599
+
715
600
  /**
716
601
  Calculates the maximum length between two pixels of the Roi.
717
602
  */
718
-
719
-
720
603
  get maxLength() {
721
604
  if (!this.computed.maxLength) {
722
605
  let maxLength = Math.sqrt(Math.pow(this.maxLengthPoints[0][0] - this.maxLengthPoints[1][0], 2) + Math.pow(this.maxLengthPoints[0][1] - this.maxLengthPoints[1][1], 2));
723
606
  this.computed.maxLength = maxLength;
724
607
  }
725
-
726
608
  return this.computed.maxLength;
727
609
  }
728
-
729
610
  get roundness() {
730
611
  /*Slide 24 https://static.horiba.com/fileadmin/Horiba/Products/Scientific/Particle_Characterization/Webinars/Slides/TE011.pdf */
731
612
  return 4 * this.surface / (Math.PI * this.feretDiameters.max ** 2);
732
613
  }
733
-
734
614
  get sphericity() {
735
615
  return 2 * Math.sqrt(this.surface * Math.PI) / this.perimeter;
736
616
  }
737
-
738
617
  get solidity() {
739
618
  return this.surface / this.convexHull.surface;
740
619
  }
741
-
742
620
  get angle() {
743
621
  if (!this.computed.angle) {
744
622
  let points = this.maxLengthPoints;
745
623
  let angle = -Math.atan2(points[0][1] - points[1][1], points[0][0] - points[1][0]) * 180 / Math.PI;
746
624
  this.computed.angle = angle;
747
625
  }
748
-
749
626
  return this.computed.angle;
750
627
  }
751
-
752
628
  toJSON() {
753
629
  return {
754
630
  id: this.id,
@@ -776,39 +652,31 @@ class Roi {
776
652
  perimeter: this.perimeter
777
653
  };
778
654
  }
655
+ }
779
656
 
780
- } // TODO we should follow the region in order to increase the speed
781
-
782
-
657
+ // TODO we should follow the region in order to increase the speed
783
658
  exports.default = Roi;
784
-
785
659
  function getBorders(roi) {
786
660
  let roiMap = roi.map;
787
661
  let data = roiMap.data;
788
662
  let surroudingIDs = new Set(); // allows to get a unique list without indexOf
789
-
790
663
  let surroundingBorders = new Map();
791
664
  let visitedData = new Set();
792
665
  let dx = [+1, 0, -1, 0];
793
666
  let dy = [0, +1, 0, -1];
794
-
795
667
  for (let x = roi.minX; x <= roi.maxX; x++) {
796
668
  for (let y = roi.minY; y <= roi.maxY; y++) {
797
669
  let target = x + y * roiMap.width;
798
-
799
670
  if (data[target] === roi.id) {
800
671
  for (let dir = 0; dir < 4; dir++) {
801
672
  let newX = x + dx[dir];
802
673
  let newY = y + dy[dir];
803
-
804
674
  if (newX >= 0 && newY >= 0 && newX < roiMap.width && newY < roiMap.height) {
805
675
  let neighbour = newX + newY * roiMap.width;
806
-
807
676
  if (data[neighbour] !== roi.id && !visitedData.has(neighbour)) {
808
677
  visitedData.add(neighbour);
809
678
  surroudingIDs.add(data[neighbour]);
810
679
  let surroundingBorder = surroundingBorders.get(data[neighbour]);
811
-
812
680
  if (!surroundingBorder) {
813
681
  surroundingBorders.set(data[neighbour], 1);
814
682
  } else {
@@ -820,7 +688,6 @@ function getBorders(roi) {
820
688
  }
821
689
  }
822
690
  }
823
-
824
691
  let ids = Array.from(surroudingIDs);
825
692
  let borderLengths = ids.map(function (id) {
826
693
  return surroundingBorders.get(id);
@@ -830,46 +697,41 @@ function getBorders(roi) {
830
697
  lengths: borderLengths
831
698
  };
832
699
  }
833
-
834
700
  function getBoxIDs(roi) {
835
701
  let surroundingIDs = new Set(); // allows to get a unique list without indexOf
836
702
 
837
703
  let roiMap = roi.map;
838
- let data = roiMap.data; // we check the first line and the last line
704
+ let data = roiMap.data;
839
705
 
706
+ // we check the first line and the last line
840
707
  for (let y of [0, roi.height - 1]) {
841
708
  for (let x = 0; x < roi.width; x++) {
842
709
  let target = (y + roi.minY) * roiMap.width + x + roi.minX;
843
-
844
710
  if (x - roi.minX > 0 && data[target] === roi.id && data[target - 1] !== roi.id) {
845
711
  let value = data[target - 1];
846
712
  surroundingIDs.add(value);
847
713
  }
848
-
849
714
  if (roiMap.width - x - roi.minX > 1 && data[target] === roi.id && data[target + 1] !== roi.id) {
850
715
  let value = data[target + 1];
851
716
  surroundingIDs.add(value);
852
717
  }
853
718
  }
854
- } // we check the first column and the last column
855
-
719
+ }
856
720
 
721
+ // we check the first column and the last column
857
722
  for (let x of [0, roi.width - 1]) {
858
723
  for (let y = 0; y < roi.height; y++) {
859
724
  let target = (y + roi.minY) * roiMap.width + x + roi.minX;
860
-
861
725
  if (y - roi.minY > 0 && data[target] === roi.id && data[target - roiMap.width] !== roi.id) {
862
726
  let value = data[target - roiMap.width];
863
727
  surroundingIDs.add(value);
864
728
  }
865
-
866
729
  if (roiMap.height - y - roi.minY > 1 && data[target] === roi.id && data[target + roiMap.width] !== roi.id) {
867
730
  let value = data[target + roiMap.width];
868
731
  surroundingIDs.add(value);
869
732
  }
870
733
  }
871
734
  }
872
-
873
735
  return Array.from(surroundingIDs); // the selection takes the whole rectangle
874
736
  }
875
737
 
@@ -878,49 +740,38 @@ function getBox(roi) {
878
740
  let roiMap = roi.map;
879
741
  let data = roiMap.data;
880
742
  let topBottom = [0];
881
-
882
743
  if (roi.height > 1) {
883
744
  topBottom[1] = roi.height - 1;
884
745
  }
885
-
886
746
  for (let y of topBottom) {
887
747
  for (let x = 1; x < roi.width - 1; x++) {
888
748
  let target = (y + roi.minY) * roiMap.width + x + roi.minX;
889
-
890
749
  if (data[target] === roi.id) {
891
750
  total++;
892
751
  }
893
752
  }
894
753
  }
895
-
896
754
  let leftRight = [0];
897
-
898
755
  if (roi.width > 1) {
899
756
  leftRight[1] = roi.width - 1;
900
757
  }
901
-
902
758
  for (let x of leftRight) {
903
759
  for (let y = 0; y < roi.height; y++) {
904
760
  let target = (y + roi.minY) * roiMap.width + x + roi.minX;
905
-
906
761
  if (data[target] === roi.id) {
907
762
  total++;
908
763
  }
909
764
  }
910
765
  }
911
-
912
766
  return total;
913
767
  }
914
-
915
768
  function getBorder(roi) {
916
769
  let total = 0;
917
770
  let roiMap = roi.map;
918
771
  let data = roiMap.data;
919
-
920
772
  for (let x = 1; x < roi.width - 1; x++) {
921
773
  for (let y = 1; y < roi.height - 1; y++) {
922
774
  let target = (y + roi.minY) * roiMap.width + x + roi.minX;
923
-
924
775
  if (data[target] === roi.id) {
925
776
  // if a point around is not roi.id it is a border
926
777
  if (data[target - 1] !== roi.id || data[target + 1] !== roi.id || data[target - roiMap.width] !== roi.id || data[target + roiMap.width] !== roi.id) {
@@ -929,10 +780,8 @@ function getBorder(roi) {
929
780
  }
930
781
  }
931
782
  }
932
-
933
783
  return total + roi.box;
934
784
  }
935
-
936
785
  function getPerimeterInfo(roi) {
937
786
  let roiMap = roi.map;
938
787
  let data = roiMap.data;
@@ -940,61 +789,49 @@ function getPerimeterInfo(roi) {
940
789
  let two = 0;
941
790
  let three = 0;
942
791
  let four = 0;
943
-
944
792
  for (let x = 0; x < roi.width; x++) {
945
793
  for (let y = 0; y < roi.height; y++) {
946
794
  let target = (y + roi.minY) * roiMap.width + x + roi.minX;
947
-
948
795
  if (data[target] === roi.id) {
949
796
  let nbAround = 0;
950
-
951
797
  if (x === 0) {
952
798
  nbAround++;
953
799
  } else if (roi.externalIDs.includes(data[target - 1])) {
954
800
  nbAround++;
955
801
  }
956
-
957
802
  if (x === roi.width - 1) {
958
803
  nbAround++;
959
804
  } else if (roi.externalIDs.includes(data[target + 1])) {
960
805
  nbAround++;
961
806
  }
962
-
963
807
  if (y === 0) {
964
808
  nbAround++;
965
809
  } else if (roi.externalIDs.includes(data[target - roiMap.width])) {
966
810
  nbAround++;
967
811
  }
968
-
969
812
  if (y === roi.height - 1) {
970
813
  nbAround++;
971
814
  } else if (roi.externalIDs.includes(data[target + roiMap.width])) {
972
815
  nbAround++;
973
816
  }
974
-
975
817
  switch (nbAround) {
976
818
  case 1:
977
819
  one++;
978
820
  break;
979
-
980
821
  case 2:
981
822
  two++;
982
823
  break;
983
-
984
824
  case 3:
985
825
  three++;
986
826
  break;
987
-
988
827
  case 4:
989
828
  four++;
990
829
  break;
991
-
992
830
  default:
993
831
  }
994
832
  }
995
833
  }
996
834
  }
997
-
998
835
  return {
999
836
  one,
1000
837
  two,
@@ -1002,16 +839,13 @@ function getPerimeterInfo(roi) {
1002
839
  four
1003
840
  };
1004
841
  }
1005
-
1006
842
  function getExternal(roi) {
1007
843
  let total = 0;
1008
844
  let roiMap = roi.map;
1009
845
  let data = roiMap.data;
1010
-
1011
846
  for (let x = 1; x < roi.width - 1; x++) {
1012
847
  for (let y = 1; y < roi.height - 1; y++) {
1013
848
  let target = (y + roi.minY) * roiMap.width + x + roi.minX;
1014
-
1015
849
  if (data[target] === roi.id) {
1016
850
  // if a point around is not roi.id it is a border
1017
851
  if (roi.externalIDs.includes(data[target - 1]) || roi.externalIDs.includes(data[target + 1]) || roi.externalIDs.includes(data[target - roiMap.width]) || roi.externalIDs.includes(data[target + roiMap.width])) {
@@ -1020,71 +854,58 @@ function getExternal(roi) {
1020
854
  }
1021
855
  }
1022
856
  }
1023
-
1024
857
  return total + roi.box;
1025
858
  }
1026
-
1027
859
  function getHolesInfo(roi) {
1028
860
  let surface = 0;
1029
861
  let width = roi.map.width;
1030
862
  let data = roi.map.data;
1031
-
1032
863
  for (let x = 1; x < roi.width - 1; x++) {
1033
864
  for (let y = 1; y < roi.height - 1; y++) {
1034
865
  let target = (y + roi.minY) * width + x + roi.minX;
1035
-
1036
866
  if (roi.internalIDs.includes(data[target]) && data[target] !== roi.id) {
1037
867
  surface++;
1038
868
  }
1039
869
  }
1040
870
  }
1041
-
1042
871
  return {
1043
872
  number: roi.internalIDs.length - 1,
1044
873
  surface
1045
874
  };
1046
875
  }
876
+
1047
877
  /*
1048
878
  We will calculate all the ids of the map that are "internal"
1049
879
  This will allow to extract the 'plain' image
1050
880
  */
1051
-
1052
-
1053
881
  function getInternalIDs(roi) {
1054
882
  let internal = [roi.id];
1055
883
  let roiMap = roi.map;
1056
884
  let data = roiMap.data;
1057
-
1058
885
  if (roi.height > 2) {
1059
886
  for (let x = 0; x < roi.width; x++) {
1060
887
  let target = roi.minY * roiMap.width + x + roi.minX;
1061
-
1062
888
  if (internal.includes(data[target])) {
1063
889
  let id = data[target + roiMap.width];
1064
-
1065
890
  if (!internal.includes(id) && !roi.boxIDs.includes(id)) {
1066
891
  internal.push(id);
1067
892
  }
1068
893
  }
1069
894
  }
1070
895
  }
1071
-
1072
896
  let array = new Array(4);
1073
-
1074
897
  for (let x = 1; x < roi.width - 1; x++) {
1075
898
  for (let y = 1; y < roi.height - 1; y++) {
1076
899
  let target = (y + roi.minY) * roiMap.width + x + roi.minX;
1077
-
1078
900
  if (internal.includes(data[target])) {
1079
901
  // we check if one of the neighbour is not yet in
902
+
1080
903
  array[0] = data[target - 1];
1081
904
  array[1] = data[target + 1];
1082
905
  array[2] = data[target - roiMap.width];
1083
906
  array[3] = data[target + roiMap.width];
1084
-
1085
907
  for (let i = 0; i < 4; i++) {
1086
908
  let id = array[i];
1087
-
1088
909
  if (!internal.includes(id) && !roi.boxIDs.includes(id)) {
1089
910
  internal.push(id);
1090
911
  }
@@ -1092,6 +913,5 @@ function getInternalIDs(roi) {
1092
913
  }
1093
914
  }
1094
915
  }
1095
-
1096
916
  return internal;
1097
917
  }