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