image-js 0.35.2 → 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.
- package/index.d.ts +2 -9
- package/lib/browser/environment.js +0 -6
- package/lib/browser/worker/extend.js +0 -3
- package/lib/browser/worker/process/background.js +0 -12
- package/lib/browser/worker/worker.js +0 -17
- package/lib/image/Image.js +18 -51
- package/lib/image/compute/colorHistogram.js +0 -8
- package/lib/image/compute/countAlphaPixels.js +0 -3
- package/lib/image/compute/extendedPoints.js +2 -7
- package/lib/image/compute/histogram.js +6 -25
- package/lib/image/compute/localMaxima.js +2 -10
- package/lib/image/compute/max.js +0 -5
- package/lib/image/compute/mean.js +0 -4
- package/lib/image/compute/median.js +0 -4
- package/lib/image/compute/min.js +0 -5
- package/lib/image/compute/minimalBoundingRectangle.js +5 -18
- package/lib/image/compute/moment.js +0 -3
- package/lib/image/compute/monotoneChainConvexHull.js +0 -3
- package/lib/image/compute/points.js +0 -3
- package/lib/image/compute/relativePosition.js +2 -8
- package/lib/image/compute/sum.js +0 -5
- package/lib/image/core/bitMethods.js +0 -11
- package/lib/image/core/checkProcessable.js +0 -13
- package/lib/image/core/environment.js +0 -8
- package/lib/image/core/export.js +0 -38
- package/lib/image/core/extend.js +0 -13
- package/lib/image/core/getRGBAData.js +0 -15
- package/lib/image/core/kind.js +4 -28
- package/lib/image/core/kindNames.js +1 -0
- package/lib/image/core/load.js +1 -53
- package/lib/image/core/mediaTypes.js +0 -2
- package/lib/image/core/valueMethods.js +0 -13
- package/lib/image/extend.js +7 -83
- package/lib/image/filter/abs.js +0 -3
- package/lib/image/filter/add.js +2 -8
- package/lib/image/filter/background.js +0 -9
- package/lib/image/filter/blurFilter.js +0 -6
- package/lib/image/filter/divide.js +0 -8
- package/lib/image/filter/flipX.js +0 -5
- package/lib/image/filter/flipY.js +0 -4
- package/lib/image/filter/gaussianFilter.js +0 -5
- package/lib/image/filter/gradientFilter.js +0 -10
- package/lib/image/filter/hypotenuse.js +0 -13
- package/lib/image/filter/invert.js +0 -9
- package/lib/image/filter/level.js +1 -19
- package/lib/image/filter/medianFilter.js +0 -15
- package/lib/image/filter/multiply.js +0 -10
- package/lib/image/filter/scharrFilter.js +0 -4
- package/lib/image/filter/sobelFilter.js +0 -4
- package/lib/image/filter/subtract.js +0 -8
- package/lib/image/filter/subtractImage.js +0 -10
- package/lib/image/internal/checks.js +1 -9
- package/lib/image/internal/clamp.js +0 -1
- package/lib/image/internal/copy.js +0 -2
- package/lib/image/internal/copyAlphaChannel.js +0 -1
- package/lib/image/internal/getImageParameters.js +0 -1
- package/lib/image/internal/getOutputImage.js +1 -13
- package/lib/image/model/model.js +1 -1
- package/lib/image/morphology/blackHat.js +0 -5
- package/lib/image/morphology/close.js +0 -5
- package/lib/image/morphology/dilate.js +0 -40
- package/lib/image/morphology/erode.js +0 -40
- package/lib/image/morphology/morphologicalGradient.js +0 -5
- package/lib/image/morphology/open.js +0 -5
- package/lib/image/morphology/topHat.js +0 -5
- package/lib/image/operator/cannyEdge.js +0 -3
- package/lib/image/operator/convolution.js +9 -34
- package/lib/image/operator/convolutionSeparable.js +0 -10
- package/lib/image/operator/extract.js +4 -13
- package/lib/image/operator/floodFill.js +2 -15
- package/lib/image/operator/getSeparatedKernel.js +0 -2
- package/lib/image/operator/paintLabels.js +2 -13
- package/lib/image/operator/paintMasks.js +2 -12
- package/lib/image/operator/paintPoints.js +0 -9
- package/lib/image/operator/paintPolygon.js +0 -14
- package/lib/image/operator/paintPolygons.js +0 -4
- package/lib/image/operator/paintPolyline.js +0 -7
- package/lib/image/operator/paintPolylines.js +0 -4
- package/lib/image/roi/Roi.js +27 -207
- package/lib/image/roi/RoiLayer.js +1 -22
- package/lib/image/roi/RoiMap.js +5 -38
- package/lib/image/roi/creator/fromMask.js +4 -22
- package/lib/image/roi/creator/fromMaskConnectedComponentLabelingAlgorithm.js +2 -20
- package/lib/image/roi/creator/fromMaxima.js +10 -43
- package/lib/image/roi/creator/fromPoints.js +2 -10
- package/lib/image/roi/creator/fromWaterShed.js +6 -17
- package/lib/image/roi/feretDiameters.js +9 -21
- package/lib/image/roi/manager.js +30 -119
- package/lib/image/roi/util/commonBorderLength.js +5 -16
- package/lib/image/roi/util/mergeRoi.js +2 -21
- package/lib/image/transform/cmyk.js +0 -9
- package/lib/image/transform/colorDepth.js +0 -12
- package/lib/image/transform/crop.js +0 -20
- package/lib/image/transform/cropAlpha.js +0 -11
- package/lib/image/transform/grey.js +0 -16
- package/lib/image/transform/greyAlgorithms.js +1 -24
- package/lib/image/transform/hsl.js +0 -16
- package/lib/image/transform/hsv.js +0 -15
- package/lib/image/transform/insert.js +0 -6
- package/lib/image/transform/mask/huang.js +3 -18
- package/lib/image/transform/mask/intermodes.js +3 -14
- package/lib/image/transform/mask/isodata.js +0 -14
- package/lib/image/transform/mask/li.js +12 -42
- package/lib/image/transform/mask/mask.js +1 -13
- package/lib/image/transform/mask/maxEntropy.js +8 -25
- package/lib/image/transform/mask/mean.js +1 -3
- package/lib/image/transform/mask/minError.js +10 -21
- package/lib/image/transform/mask/minimum.js +0 -20
- package/lib/image/transform/mask/moments.js +4 -17
- package/lib/image/transform/mask/otsu.js +1 -7
- package/lib/image/transform/mask/percentile.js +0 -8
- package/lib/image/transform/mask/renyiEntropy.js +8 -34
- package/lib/image/transform/mask/shanbhag.js +8 -25
- package/lib/image/transform/mask/thresholdAlgorithms.js +1 -17
- package/lib/image/transform/mask/triangle.js +13 -29
- package/lib/image/transform/mask/yen.js +2 -14
- package/lib/image/transform/pad.js +0 -20
- package/lib/image/transform/resize/nearestNeighbor.js +0 -6
- package/lib/image/transform/resize/resize.js +0 -16
- package/lib/image/transform/rgba.js +0 -9
- package/lib/image/transform/rgba8.js +0 -3
- package/lib/image/transform/rotate.js +0 -29
- package/lib/image/transform/rotateFree.js +0 -31
- package/lib/image/transform/warping.js +2 -35
- package/lib/image/utility/combineChannels.js +0 -11
- package/lib/image/utility/getBestMatch.js +2 -13
- package/lib/image/utility/getChannel.js +0 -10
- package/lib/image/utility/getClosestCommonParent.js +6 -23
- package/lib/image/utility/getColumn.js +0 -4
- package/lib/image/utility/getIntersection.js +2 -18
- package/lib/image/utility/getMatrix.js +0 -7
- package/lib/image/utility/getPixelsArray.js +0 -5
- package/lib/image/utility/getPixelsGrid.js +0 -11
- package/lib/image/utility/getRow.js +0 -4
- package/lib/image/utility/getSimilarity.js +3 -17
- package/lib/image/utility/getThreshold.js +0 -4
- package/lib/image/utility/setBorder.js +0 -16
- package/lib/image/utility/setChannel.js +0 -6
- package/lib/image/utility/setMatrix.js +0 -6
- package/lib/image/utility/split.js +2 -15
- package/lib/index.js +0 -12
- package/lib/kernel/kernel.js +0 -3
- package/lib/kernel/laplacianOfGaussian.js +1 -7
- package/lib/node_modules/test/binary.js +0 -3
- package/lib/node_modules/test/oneRoi.js +0 -2
- package/lib/stack/Stack.js +2 -35
- package/lib/stack/compute/histogram.js +0 -4
- package/lib/stack/compute/histograms.js +0 -4
- package/lib/stack/compute/max.js +0 -3
- package/lib/stack/compute/median.js +0 -4
- package/lib/stack/compute/min.js +0 -3
- package/lib/stack/extend.js +1 -11
- package/lib/stack/transform/matchAndCrop.js +6 -19
- package/lib/stack/utility/averageImage.js +0 -9
- package/lib/stack/utility/maxImage.js +0 -7
- package/lib/stack/utility/minImage.js +0 -7
- package/lib/util/Shape.js +3 -40
- package/lib/util/base64.js +3 -14
- package/lib/util/channel.js +1 -35
- package/lib/util/color.js +1 -25
- package/lib/util/converter.js +1 -13
- package/lib/util/deepValue.js +0 -3
- package/lib/util/histogram.js +1 -12
- package/lib/util/kernel.js +2 -12
- package/lib/util/matrix.js +0 -13
- package/lib/util/points.js +12 -35
- package/lib/util/value.js +0 -7
- package/lib/util/zerosMatrix.js +0 -3
- package/package.json +1 -1
package/lib/image/roi/Roi.js
CHANGED
|
@@ -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');
|
|
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 = [];
|
|
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
|
-
|
|
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;
|
|
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
|
-
}
|
|
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
|
}
|