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
|
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = fromMaxima;
|
|
7
|
-
|
|
8
7
|
var _RoiMap = _interopRequireDefault(require("../RoiMap"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* @memberof RoiManager
|
|
14
11
|
* @instance
|
|
@@ -29,24 +26,21 @@ function fromMaxima(options = {}) {
|
|
|
29
26
|
components: [1]
|
|
30
27
|
});
|
|
31
28
|
const PROCESS_TOP = 1;
|
|
32
|
-
const PROCESS_NORMAL = 2;
|
|
29
|
+
const PROCESS_NORMAL = 2;
|
|
33
30
|
|
|
31
|
+
// split will always return an array of images
|
|
34
32
|
let positiveID = 0;
|
|
35
33
|
let negativeID = 0;
|
|
36
34
|
let data = new Int16Array(image.size); // maxValue: 32767, minValue: -32768
|
|
37
|
-
|
|
38
35
|
let processed = new Int8Array(image.size);
|
|
39
36
|
let variations = new Float32Array(image.size);
|
|
40
37
|
let MAX_ARRAY = 0x0fffff; // should be enough for most of the cases
|
|
41
|
-
|
|
42
38
|
let xToProcess = new Uint16Array(MAX_ARRAY + 1); // assign dynamically ????
|
|
43
|
-
|
|
44
39
|
let yToProcess = new Uint16Array(MAX_ARRAY + 1); // mask +1 is of course mandatory !!!
|
|
45
40
|
|
|
46
41
|
let from = 0;
|
|
47
42
|
let to = 0;
|
|
48
43
|
let xToProcessTop = new Uint16Array(MAX_ARRAY + 1); // assign dynamically ????
|
|
49
|
-
|
|
50
44
|
let yToProcessTop = new Uint16Array(MAX_ARRAY + 1); // mask +1 is of course mandatory !!!
|
|
51
45
|
|
|
52
46
|
let fromTop = 0;
|
|
@@ -54,73 +48,61 @@ function fromMaxima(options = {}) {
|
|
|
54
48
|
appendMaxima(image, {
|
|
55
49
|
maxima: !invert
|
|
56
50
|
});
|
|
57
|
-
|
|
58
51
|
while (from < to) {
|
|
59
52
|
let currentX = xToProcess[from & MAX_ARRAY];
|
|
60
53
|
let currentY = yToProcess[from & MAX_ARRAY];
|
|
61
54
|
process(currentX, currentY, PROCESS_NORMAL);
|
|
62
55
|
from++;
|
|
63
56
|
}
|
|
57
|
+
return new _RoiMap.default(image, data);
|
|
64
58
|
|
|
65
|
-
|
|
59
|
+
// we will look for the maxima (or minima) that is present in the picture
|
|
66
60
|
// a maxima is a point that is surrounded by lower values
|
|
67
61
|
// should deal with allowCorner and invert
|
|
68
|
-
|
|
69
62
|
function appendMaxima({
|
|
70
63
|
maxima = true
|
|
71
64
|
}) {
|
|
72
65
|
for (let y = 1; y < image.height - 1; y++) {
|
|
73
66
|
for (let x = 1; x < image.width - 1; x++) {
|
|
74
67
|
let index = x + y * image.width;
|
|
75
|
-
|
|
76
68
|
if (processed[index] === 0) {
|
|
77
69
|
let currentValue = maxima ? image.data[index] : -image.data[x + y * image.width];
|
|
78
|
-
|
|
79
70
|
if (image.data[y * image.width + x - 1] > currentValue) {
|
|
80
71
|
// LEFT
|
|
81
72
|
continue;
|
|
82
73
|
}
|
|
83
|
-
|
|
84
74
|
if (image.data[y * image.width + x + 1] > currentValue) {
|
|
85
75
|
// RIGHT
|
|
86
76
|
continue;
|
|
87
77
|
}
|
|
88
|
-
|
|
89
78
|
if (image.data[(y - 1) * image.width + x] > currentValue) {
|
|
90
79
|
// TOP
|
|
91
80
|
continue;
|
|
92
81
|
}
|
|
93
|
-
|
|
94
82
|
if (image.data[(y + 1) * image.width + x] > currentValue) {
|
|
95
83
|
// BOTTOM
|
|
96
84
|
continue;
|
|
97
85
|
}
|
|
98
|
-
|
|
99
86
|
if (allowCorner) {
|
|
100
87
|
if (image.data[(y - 1) * image.width + x - 1] > currentValue) {
|
|
101
88
|
// LEFT TOP
|
|
102
89
|
continue;
|
|
103
90
|
}
|
|
104
|
-
|
|
105
91
|
if (image.data[(y - 1) * image.width + x + 1] > currentValue) {
|
|
106
92
|
// RIGHT TOP
|
|
107
93
|
continue;
|
|
108
94
|
}
|
|
109
|
-
|
|
110
95
|
if (image.data[(y + 1) * image.width + x - 1] > currentValue) {
|
|
111
96
|
// LEFT BOTTOM
|
|
112
97
|
continue;
|
|
113
98
|
}
|
|
114
|
-
|
|
115
99
|
if (image.data[(y + 1) * image.width + x + 1] > currentValue) {
|
|
116
100
|
// RIGHT BOTTOM
|
|
117
101
|
continue;
|
|
118
102
|
}
|
|
119
103
|
}
|
|
120
|
-
|
|
121
104
|
data[index] = maxima ? ++positiveID : --negativeID;
|
|
122
105
|
let valid = processTop(x, y, PROCESS_TOP);
|
|
123
|
-
|
|
124
106
|
if (!valid) {
|
|
125
107
|
if (maxima) {
|
|
126
108
|
--positiveID;
|
|
@@ -131,28 +113,25 @@ function fromMaxima(options = {}) {
|
|
|
131
113
|
}
|
|
132
114
|
}
|
|
133
115
|
}
|
|
134
|
-
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// we will try to get all the points of the top (same value)
|
|
135
119
|
// and to check if the whole group is surrounded by lower value
|
|
136
120
|
// as soon as one of them if not part we need to reverse the process
|
|
137
121
|
// and just for get those points
|
|
138
|
-
|
|
139
|
-
|
|
140
122
|
function processTop(xToProcess, yToProcess) {
|
|
141
123
|
let currentTo = to; // in case if fails we come back
|
|
142
|
-
|
|
143
124
|
fromTop = 0;
|
|
144
125
|
toTop = 1;
|
|
145
126
|
xToProcessTop[0] = xToProcess;
|
|
146
127
|
yToProcessTop[0] = yToProcess;
|
|
147
128
|
let valid = true;
|
|
148
|
-
|
|
149
129
|
while (fromTop < toTop) {
|
|
150
130
|
let currentX = xToProcessTop[fromTop & MAX_ARRAY];
|
|
151
131
|
let currentY = yToProcessTop[fromTop & MAX_ARRAY];
|
|
152
132
|
valid &= process(currentX, currentY, PROCESS_TOP);
|
|
153
133
|
fromTop++;
|
|
154
134
|
}
|
|
155
|
-
|
|
156
135
|
if (!valid) {
|
|
157
136
|
// need to clear all the calculated data because the top is not surrounded by negative values
|
|
158
137
|
for (let i = 0; i < toTop; i++) {
|
|
@@ -161,33 +140,27 @@ function fromMaxima(options = {}) {
|
|
|
161
140
|
let index = currentY * image.width + currentX;
|
|
162
141
|
data[index] = 0;
|
|
163
142
|
}
|
|
164
|
-
|
|
165
143
|
to = currentTo;
|
|
166
144
|
}
|
|
167
|
-
|
|
168
145
|
return valid;
|
|
169
146
|
}
|
|
147
|
+
|
|
170
148
|
/*
|
|
171
149
|
For a specific point we will check the points around, increase the area of interests and add
|
|
172
150
|
them to the processing list
|
|
173
151
|
type=0 : top
|
|
174
152
|
type=1 : normal
|
|
175
153
|
*/
|
|
176
|
-
|
|
177
|
-
|
|
178
154
|
function process(xCenter, yCenter, type) {
|
|
179
155
|
let currentID = data[yCenter * image.width + xCenter];
|
|
180
156
|
let currentValue = image.data[yCenter * image.width + xCenter];
|
|
181
|
-
|
|
182
157
|
for (let y = yCenter - 1; y <= yCenter + 1; y++) {
|
|
183
158
|
for (let x = xCenter - 1; x <= xCenter + 1; x++) {
|
|
184
159
|
let index = y * image.width + x;
|
|
185
|
-
|
|
186
160
|
if (processed[index] === 0) {
|
|
187
|
-
processed[index] = 1;
|
|
188
|
-
|
|
161
|
+
processed[index] = 1;
|
|
162
|
+
// we store the variation compare to the parent pixel
|
|
189
163
|
variations[index] = image.data[index] - currentValue;
|
|
190
|
-
|
|
191
164
|
switch (type) {
|
|
192
165
|
case PROCESS_TOP:
|
|
193
166
|
if (variations[index] === 0) {
|
|
@@ -196,7 +169,6 @@ function fromMaxima(options = {}) {
|
|
|
196
169
|
if (x === 0 || y === 0 || x === image.width - 1 || y === image.height - 1) {
|
|
197
170
|
return false;
|
|
198
171
|
}
|
|
199
|
-
|
|
200
172
|
data[index] = currentID;
|
|
201
173
|
xToProcessTop[toTop & MAX_ARRAY] = x;
|
|
202
174
|
yToProcessTop[toTop & MAX_ARRAY] = y;
|
|
@@ -213,9 +185,7 @@ function fromMaxima(options = {}) {
|
|
|
213
185
|
to++;
|
|
214
186
|
}
|
|
215
187
|
}
|
|
216
|
-
|
|
217
188
|
break;
|
|
218
|
-
|
|
219
189
|
case PROCESS_NORMAL:
|
|
220
190
|
if (variations[index] <= 0) {
|
|
221
191
|
// we look for maxima
|
|
@@ -224,16 +194,13 @@ function fromMaxima(options = {}) {
|
|
|
224
194
|
yToProcess[to & MAX_ARRAY] = y;
|
|
225
195
|
to++;
|
|
226
196
|
}
|
|
227
|
-
|
|
228
197
|
break;
|
|
229
|
-
|
|
230
198
|
default:
|
|
231
199
|
throw new Error('unreachable');
|
|
232
200
|
}
|
|
233
201
|
}
|
|
234
202
|
}
|
|
235
203
|
}
|
|
236
|
-
|
|
237
204
|
return true;
|
|
238
205
|
}
|
|
239
206
|
}
|
|
@@ -4,13 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = fromPoints;
|
|
7
|
-
|
|
8
7
|
var _Shape = _interopRequireDefault(require("../../../util/Shape"));
|
|
9
|
-
|
|
10
8
|
var _RoiMap = _interopRequireDefault(require("../RoiMap"));
|
|
11
|
-
|
|
12
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
|
|
14
10
|
/**
|
|
15
11
|
* @memberof RoiManager
|
|
16
12
|
* @instance
|
|
@@ -19,27 +15,23 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
19
15
|
* @return {RoiMap}
|
|
20
16
|
*/
|
|
21
17
|
function fromPoints(pointsToPaint, options = {}) {
|
|
22
|
-
let shape = new _Shape.default(options);
|
|
18
|
+
let shape = new _Shape.default(options);
|
|
23
19
|
|
|
20
|
+
// based on a binary image we will create plenty of small images
|
|
24
21
|
let data = new Int16Array(this.size); // maxValue: 32767, minValue: -32768
|
|
25
|
-
|
|
26
22
|
let positiveID = 0;
|
|
27
23
|
let shapePoints = shape.getPoints();
|
|
28
|
-
|
|
29
24
|
for (let i = 0; i < pointsToPaint.length; i++) {
|
|
30
25
|
positiveID++;
|
|
31
26
|
let xP = pointsToPaint[i][0];
|
|
32
27
|
let yP = pointsToPaint[i][1];
|
|
33
|
-
|
|
34
28
|
for (let j = 0; j < shapePoints.length; j++) {
|
|
35
29
|
let xS = shapePoints[j][0];
|
|
36
30
|
let yS = shapePoints[j][1];
|
|
37
|
-
|
|
38
31
|
if (xP + xS >= 0 && yP + yS >= 0 && xP + xS < this.width && yP + yS < this.height) {
|
|
39
32
|
data[xP + xS + (yP + yS) * this.width] = positiveID;
|
|
40
33
|
}
|
|
41
34
|
}
|
|
42
35
|
}
|
|
43
|
-
|
|
44
36
|
return new _RoiMap.default(this, data);
|
|
45
37
|
}
|
|
@@ -4,15 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = fromWaterShed;
|
|
7
|
-
|
|
8
7
|
var _jsPriorityQueue = _interopRequireDefault(require("js-priority-queue"));
|
|
9
|
-
|
|
10
8
|
var _dxdy = require("../../../util/dxdy.js");
|
|
11
|
-
|
|
12
9
|
var _RoiMap = _interopRequireDefault(require("../RoiMap"));
|
|
13
|
-
|
|
14
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
-
|
|
16
11
|
/**
|
|
17
12
|
* This method allows to create a ROIMap using the water shed algorithm. By default this algorithm
|
|
18
13
|
* will fill the holes and therefore the lowest value of the image (black zones).
|
|
@@ -48,21 +43,22 @@ function fromWaterShed(options = {}) {
|
|
|
48
43
|
bitDepth: [8, 16],
|
|
49
44
|
components: 1
|
|
50
45
|
});
|
|
46
|
+
|
|
51
47
|
/*
|
|
52
48
|
We need to invert the logic because we are always using method to look for maxima and not minima and
|
|
53
49
|
here water is expected to fill the minima first ...
|
|
54
50
|
*/
|
|
55
51
|
|
|
56
|
-
invert = !invert;
|
|
57
|
-
// or it is gonna take the minimum locals of the image by default.
|
|
52
|
+
invert = !invert;
|
|
58
53
|
|
|
54
|
+
// WaterShed is done from points in the image. We can either specify those points in options,
|
|
55
|
+
// or it is gonna take the minimum locals of the image by default.
|
|
59
56
|
if (!points) {
|
|
60
57
|
points = currentImage.getLocalMaxima({
|
|
61
58
|
invert,
|
|
62
59
|
mask
|
|
63
60
|
});
|
|
64
61
|
}
|
|
65
|
-
|
|
66
62
|
let maskExpectedValue = invert ? 0 : 1;
|
|
67
63
|
let data = new Int16Array(currentImage.size);
|
|
68
64
|
let width = currentImage.width;
|
|
@@ -71,32 +67,26 @@ function fromWaterShed(options = {}) {
|
|
|
71
67
|
comparator: (a, b) => a[2] - b[2],
|
|
72
68
|
strategy: _jsPriorityQueue.default.BinaryHeapStrategy
|
|
73
69
|
});
|
|
74
|
-
|
|
75
70
|
for (let i = 0; i < points.length; i++) {
|
|
76
71
|
let index = points[i][0] + points[i][1] * width;
|
|
77
72
|
data[index] = i + 1;
|
|
78
73
|
let intensity = currentImage.data[index];
|
|
79
|
-
|
|
80
74
|
if (invert && intensity <= fillMaxValue || !invert && intensity >= fillMaxValue) {
|
|
81
75
|
toProcess.queue([points[i][0], points[i][1], intensity]);
|
|
82
76
|
}
|
|
83
|
-
}
|
|
84
|
-
|
|
77
|
+
}
|
|
85
78
|
|
|
79
|
+
// Then we iterate through each points
|
|
86
80
|
while (toProcess.length > 0) {
|
|
87
81
|
let currentPoint = toProcess.dequeue();
|
|
88
82
|
let currentValueIndex = currentPoint[0] + currentPoint[1] * width;
|
|
89
|
-
|
|
90
83
|
for (let dir = 0; dir < 4; dir++) {
|
|
91
84
|
let newX = currentPoint[0] + _dxdy.dxs[dir];
|
|
92
85
|
let newY = currentPoint[1] + _dxdy.dys[dir];
|
|
93
|
-
|
|
94
86
|
if (newX >= 0 && newY >= 0 && newX < width && newY < height) {
|
|
95
87
|
let currentNeighbourIndex = newX + newY * width;
|
|
96
|
-
|
|
97
88
|
if (!mask || mask.getBit(currentNeighbourIndex) === maskExpectedValue) {
|
|
98
89
|
let intensity = currentImage.data[currentNeighbourIndex];
|
|
99
|
-
|
|
100
90
|
if (invert && intensity <= fillMaxValue || !invert && intensity >= fillMaxValue) {
|
|
101
91
|
if (data[currentNeighbourIndex] === 0) {
|
|
102
92
|
data[currentNeighbourIndex] = data[currentValueIndex];
|
|
@@ -107,6 +97,5 @@ function fromWaterShed(options = {}) {
|
|
|
107
97
|
}
|
|
108
98
|
}
|
|
109
99
|
}
|
|
110
|
-
|
|
111
100
|
return new _RoiMap.default(currentImage, data);
|
|
112
101
|
}
|
|
@@ -4,13 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = feretDiameters;
|
|
7
|
-
|
|
8
7
|
var _points = require("../../util/points");
|
|
9
|
-
|
|
10
8
|
var _monotoneChainConvexHull = _interopRequireDefault(require("../compute/monotoneChainConvexHull"));
|
|
11
|
-
|
|
12
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
|
|
14
10
|
/**
|
|
15
11
|
* Computes the Feret diameters
|
|
16
12
|
* https://www.sympatec.com/en/particle-measurement/glossary/particle-shape/#
|
|
@@ -25,7 +21,6 @@ function feretDiameters(options = {}) {
|
|
|
25
21
|
const {
|
|
26
22
|
originalPoints = _monotoneChainConvexHull.default.call(this)
|
|
27
23
|
} = options;
|
|
28
|
-
|
|
29
24
|
if (originalPoints.length === 0) {
|
|
30
25
|
return {
|
|
31
26
|
min: 0,
|
|
@@ -35,7 +30,6 @@ function feretDiameters(options = {}) {
|
|
|
35
30
|
aspectRatio: 1
|
|
36
31
|
};
|
|
37
32
|
}
|
|
38
|
-
|
|
39
33
|
if (originalPoints.length === 1) {
|
|
40
34
|
return {
|
|
41
35
|
min: 1,
|
|
@@ -45,47 +39,42 @@ function feretDiameters(options = {}) {
|
|
|
45
39
|
aspectRatio: 1
|
|
46
40
|
};
|
|
47
41
|
}
|
|
42
|
+
const temporaryPoints = new Array(originalPoints.length);
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
// CALCULATE MIN VALUE
|
|
51
45
|
let minWidth = +Infinity;
|
|
52
46
|
let minWidthAngle = 0;
|
|
53
47
|
let minLine = [];
|
|
54
|
-
|
|
55
48
|
for (let i = 0; i < originalPoints.length; i++) {
|
|
56
|
-
let angle = getAngle(originalPoints[i], originalPoints[(i + 1) % originalPoints.length]);
|
|
49
|
+
let angle = getAngle(originalPoints[i], originalPoints[(i + 1) % originalPoints.length]);
|
|
57
50
|
|
|
51
|
+
// we rotate so that it is parallel to X axis
|
|
58
52
|
(0, _points.rotate)(-angle, originalPoints, temporaryPoints);
|
|
59
53
|
let currentWidth = 0;
|
|
60
54
|
let currentMinLine = [];
|
|
61
|
-
|
|
62
55
|
for (let j = 0; j < originalPoints.length; j++) {
|
|
63
56
|
let absWidth = Math.abs(temporaryPoints[i][1] - temporaryPoints[j][1]);
|
|
64
|
-
|
|
65
57
|
if (absWidth > currentWidth) {
|
|
66
58
|
currentWidth = absWidth;
|
|
67
59
|
currentMinLine = [];
|
|
68
60
|
currentMinLine.push([temporaryPoints[j][0], temporaryPoints[i][1]], [temporaryPoints[j][0], temporaryPoints[j][1]]);
|
|
69
61
|
}
|
|
70
62
|
}
|
|
71
|
-
|
|
72
63
|
if (currentWidth < minWidth) {
|
|
73
64
|
minWidth = currentWidth;
|
|
74
65
|
minWidthAngle = angle;
|
|
75
66
|
minLine = currentMinLine;
|
|
76
67
|
}
|
|
77
68
|
}
|
|
69
|
+
(0, _points.rotate)(minWidthAngle, minLine, minLine);
|
|
78
70
|
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
// CALCULATE MAX VALUE
|
|
81
72
|
let maxWidth = 0;
|
|
82
73
|
let maxLine = [];
|
|
83
74
|
let maxSquaredWidth = 0;
|
|
84
|
-
|
|
85
75
|
for (let i = 0; i < originalPoints.length - 1; i++) {
|
|
86
76
|
for (let j = i + 1; j < originalPoints.length; j++) {
|
|
87
77
|
let currentSquaredWidth = (originalPoints[i][0] - originalPoints[j][0]) ** 2 + (originalPoints[i][1] - originalPoints[j][1]) ** 2;
|
|
88
|
-
|
|
89
78
|
if (currentSquaredWidth > maxSquaredWidth) {
|
|
90
79
|
maxSquaredWidth = currentSquaredWidth;
|
|
91
80
|
maxWidth = Math.sqrt(currentSquaredWidth);
|
|
@@ -93,7 +82,6 @@ function feretDiameters(options = {}) {
|
|
|
93
82
|
}
|
|
94
83
|
}
|
|
95
84
|
}
|
|
96
|
-
|
|
97
85
|
return {
|
|
98
86
|
min: minWidth,
|
|
99
87
|
minLine,
|
|
@@ -101,10 +89,10 @@ function feretDiameters(options = {}) {
|
|
|
101
89
|
maxLine,
|
|
102
90
|
aspectRatio: minWidth / maxWidth
|
|
103
91
|
};
|
|
104
|
-
}
|
|
105
|
-
// this is an optimized version because it assume one vector is horizontal
|
|
106
|
-
|
|
92
|
+
}
|
|
107
93
|
|
|
94
|
+
// the angle that allows to make the line going through p1 and p2 horizontal
|
|
95
|
+
// this is an optimized version because it assume one vector is horizontal
|
|
108
96
|
function getAngle(p1, p2) {
|
|
109
97
|
let diff = (0, _points.difference)(p2, p1);
|
|
110
98
|
let vector = (0, _points.normalize)(diff);
|