image-js 0.35.1 → 0.35.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +99 -35
- 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 +8 -19
- package/lib/image/operator/paintMasks.js +2 -12
- package/lib/image/operator/paintPoints.js +0 -9
- package/lib/image/operator/paintPolygon.js +1 -15
- package/lib/image/operator/paintPolygons.js +2 -6
- package/lib/image/operator/paintPolyline.js +0 -7
- package/lib/image/operator/paintPolylines.js +1 -5
- 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 +2 -2
- package/src/image/operator/paintLabels.js +6 -6
- package/src/image/operator/paintPolygon.js +1 -1
- package/src/image/operator/paintPolygons.js +2 -2
- package/src/image/operator/paintPolylines.js +1 -1
|
@@ -4,41 +4,35 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = otsu;
|
|
7
|
-
|
|
8
7
|
/*
|
|
9
8
|
* The method is present in: Otsu, N (1979), "A threshold selection method from gray-level histograms", IEEE Trans. Sys., Man., Cyber. 9: 62-66
|
|
10
9
|
* The Otsu implementation is based on: https://en.wikipedia.org/wiki/Otsu's_method
|
|
11
10
|
* @param histogram - the histogram of the image
|
|
12
11
|
* @returns {number} - the threshold
|
|
13
12
|
*/
|
|
13
|
+
|
|
14
14
|
function otsu(histogramCounts, total) {
|
|
15
15
|
let sumB = 0;
|
|
16
16
|
let wB = 0;
|
|
17
17
|
let maximum = 0;
|
|
18
18
|
let level = 0;
|
|
19
19
|
let sum1 = 0;
|
|
20
|
-
|
|
21
20
|
for (let i = 0; i < histogramCounts.length; i++) {
|
|
22
21
|
sum1 += i * histogramCounts[i];
|
|
23
22
|
}
|
|
24
|
-
|
|
25
23
|
for (let ii = 0; ii < histogramCounts.length; ii++) {
|
|
26
24
|
wB = wB + histogramCounts[ii];
|
|
27
25
|
const wF = total - wB;
|
|
28
|
-
|
|
29
26
|
if (wB === 0 || wF === 0) {
|
|
30
27
|
continue;
|
|
31
28
|
}
|
|
32
|
-
|
|
33
29
|
sumB = sumB + ii * histogramCounts[ii];
|
|
34
30
|
const mF = (sum1 - sumB) / wF;
|
|
35
31
|
const between = wB * wF * (sumB / wB - mF) * (sumB / wB - mF);
|
|
36
|
-
|
|
37
32
|
if (between >= maximum) {
|
|
38
33
|
level = ii;
|
|
39
34
|
maximum = between;
|
|
40
35
|
}
|
|
41
36
|
}
|
|
42
|
-
|
|
43
37
|
return level;
|
|
44
38
|
}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = percentile;
|
|
7
|
-
|
|
8
7
|
// See http://imagej.nih.gov/ij/download/tools/source/ij/process/AutoThresholder.java
|
|
9
8
|
// W. Doyle, "Operation useful for similarity-invariant pattern recognition,"
|
|
10
9
|
// Journal of the Association for Computing Machinery, vol. 9,pp. 259-267, 1962.
|
|
@@ -15,29 +14,22 @@ exports.default = percentile;
|
|
|
15
14
|
function percentile(histogram) {
|
|
16
15
|
let threshold = -1;
|
|
17
16
|
let percentile = 0.5; // default fraction of foreground pixels
|
|
18
|
-
|
|
19
17
|
let avec = new Array(histogram.length);
|
|
20
18
|
let total = partialSum(histogram, histogram.length - 1);
|
|
21
19
|
let temp = 1.0;
|
|
22
|
-
|
|
23
20
|
for (let i = 0; i < histogram.length; i++) {
|
|
24
21
|
avec[i] = Math.abs(partialSum(histogram, i) / total - percentile);
|
|
25
|
-
|
|
26
22
|
if (avec[i] < temp) {
|
|
27
23
|
temp = avec[i];
|
|
28
24
|
threshold = i;
|
|
29
25
|
}
|
|
30
26
|
}
|
|
31
|
-
|
|
32
27
|
return threshold;
|
|
33
28
|
}
|
|
34
|
-
|
|
35
29
|
function partialSum(histogram, endIndex) {
|
|
36
30
|
let x = 0;
|
|
37
|
-
|
|
38
31
|
for (let i = 0; i <= endIndex; i++) {
|
|
39
32
|
x += histogram[i];
|
|
40
33
|
}
|
|
41
|
-
|
|
42
34
|
return x;
|
|
43
35
|
}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = renyiEntropy;
|
|
7
|
-
|
|
8
7
|
// see https://github.com/fiji/Auto_Threshold/blob/master/src/main/java/fiji/threshold/Auto_Threshold.java
|
|
9
8
|
// Kapur J.N., Sahoo P.K., and Wong A.K.C. (1985) "A New Method for
|
|
10
9
|
// Gray-Level Picture Thresholding Using the Entropy of the Histogram"
|
|
@@ -14,18 +13,14 @@ exports.default = renyiEntropy;
|
|
|
14
13
|
// Ported to ImageJ plugin by G.Landini from E Celebi's fourier_0.8 routines
|
|
15
14
|
function renyiEntropy(histogram, total) {
|
|
16
15
|
let optThreshold; // Optimal threshold
|
|
17
|
-
|
|
18
16
|
let firstBin; // First non-zero bin
|
|
19
|
-
|
|
20
17
|
let lastBin; // last non-zero bin
|
|
21
18
|
|
|
22
19
|
let normHisto = new Array(histogram.length); // normalized histogram
|
|
23
|
-
|
|
24
20
|
let P1 = new Array(histogram.length); // acumulative normalized histogram
|
|
25
|
-
|
|
26
21
|
let P2 = new Array(histogram.length); // acumulative normalized histogram
|
|
27
|
-
// Entropy Variables
|
|
28
22
|
|
|
23
|
+
// Entropy Variables
|
|
29
24
|
let threshold1 = 0;
|
|
30
25
|
let threshold2 = 0;
|
|
31
26
|
let threshold3 = 0;
|
|
@@ -36,95 +31,76 @@ function renyiEntropy(histogram, total) {
|
|
|
36
31
|
let term2 = 1.0 / (1.0 - alpha2);
|
|
37
32
|
let alpha3 = 2.0;
|
|
38
33
|
let term3 = 1.0 / (1.0 - alpha3);
|
|
39
|
-
|
|
40
34
|
for (let ih = 0; ih < histogram.length; ih++) {
|
|
41
35
|
normHisto[ih] = histogram[ih] / total;
|
|
42
36
|
}
|
|
43
|
-
|
|
44
37
|
P1[0] = normHisto[0];
|
|
45
38
|
P2[0] = 1.0 - P1[0];
|
|
46
|
-
|
|
47
39
|
for (let ih = 1; ih < histogram.length; ih++) {
|
|
48
40
|
P1[ih] = P1[ih - 1] + normHisto[ih];
|
|
49
41
|
P2[ih] = 1.0 - P1[ih];
|
|
50
42
|
}
|
|
51
|
-
/* Determine the first non-zero bin */
|
|
52
|
-
|
|
53
43
|
|
|
44
|
+
/* Determine the first non-zero bin */
|
|
54
45
|
firstBin = 0;
|
|
55
|
-
|
|
56
46
|
for (let ih = 0; ih < histogram.length; ih++) {
|
|
57
47
|
if (Math.abs(P1[ih]) >= Number.EPSILON) {
|
|
58
48
|
firstBin = ih;
|
|
59
49
|
break;
|
|
60
50
|
}
|
|
61
51
|
}
|
|
62
|
-
/* Determine the last non-zero bin */
|
|
63
|
-
|
|
64
52
|
|
|
53
|
+
/* Determine the last non-zero bin */
|
|
65
54
|
lastBin = histogram.length - 1;
|
|
66
|
-
|
|
67
55
|
for (let ih = histogram.length - 1; ih >= firstBin; ih--) {
|
|
68
56
|
if (Math.abs(P2[ih]) >= Number.EPSILON) {
|
|
69
57
|
lastBin = ih;
|
|
70
58
|
break;
|
|
71
59
|
}
|
|
72
60
|
}
|
|
73
|
-
/* Maximum Entropy Thresholding - BEGIN */
|
|
74
61
|
|
|
62
|
+
/* Maximum Entropy Thresholding - BEGIN */
|
|
75
63
|
/* ALPHA = 1.0 */
|
|
76
|
-
|
|
77
64
|
/* Calculate the total entropy each gray-level
|
|
78
65
|
and find the threshold that maximizes it
|
|
79
66
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
67
|
for (let it = firstBin; it <= lastBin; it++) {
|
|
83
68
|
/* Entropy of the background pixels */
|
|
84
69
|
let entBack1 = 0.0;
|
|
85
70
|
let entBack2 = 0.0;
|
|
86
71
|
let entBack3 = 0.0;
|
|
87
|
-
|
|
88
72
|
for (let ih = 0; ih <= it; ih++) {
|
|
89
73
|
if (histogram[ih] !== 0) {
|
|
90
74
|
entBack1 -= normHisto[ih] / P1[it] * Math.log(normHisto[ih] / P1[it]);
|
|
91
75
|
}
|
|
92
|
-
|
|
93
76
|
entBack2 += Math.sqrt(normHisto[ih] / P1[it]);
|
|
94
77
|
entBack3 += normHisto[ih] * normHisto[ih] / (P1[it] * P1[it]);
|
|
95
78
|
}
|
|
96
|
-
/* Entropy of the object pixels */
|
|
97
|
-
|
|
98
79
|
|
|
80
|
+
/* Entropy of the object pixels */
|
|
99
81
|
let entObj1 = 0.0;
|
|
100
82
|
let entObj2 = 0.0;
|
|
101
83
|
let entObj3 = 0.0;
|
|
102
|
-
|
|
103
84
|
for (let ih = it + 1; ih < histogram.length; ih++) {
|
|
104
85
|
if (histogram[ih] !== 0) {
|
|
105
86
|
entObj1 -= normHisto[ih] / P2[it] * Math.log(normHisto[ih] / P2[it]);
|
|
106
87
|
}
|
|
107
|
-
|
|
108
88
|
entObj2 += Math.sqrt(normHisto[ih] / P2[it]);
|
|
109
89
|
entObj3 += normHisto[ih] * normHisto[ih] / (P2[it] * P2[it]);
|
|
110
90
|
}
|
|
111
|
-
/* Total entropy */
|
|
112
|
-
|
|
113
91
|
|
|
92
|
+
/* Total entropy */
|
|
114
93
|
let totEnt1 = entBack1 + entObj1;
|
|
115
94
|
let totEnt2 = term2 * (entBack2 * entObj2 > 0.0 ? Math.log(entBack2 * entObj2) : 0.0);
|
|
116
95
|
let totEnt3 = term3 * (entBack3 * entObj3 > 0.0 ? Math.log(entBack3 * entObj3) : 0.0);
|
|
117
|
-
|
|
118
96
|
if (totEnt1 > maxEnt1) {
|
|
119
97
|
maxEnt1 = totEnt1;
|
|
120
98
|
threshold1 = it;
|
|
121
99
|
}
|
|
122
|
-
|
|
123
100
|
if (totEnt2 > maxEnt2) {
|
|
124
101
|
maxEnt2 = totEnt2;
|
|
125
102
|
threshold2 = it;
|
|
126
103
|
}
|
|
127
|
-
|
|
128
104
|
if (totEnt3 > maxEnt3) {
|
|
129
105
|
maxEnt3 = totEnt3;
|
|
130
106
|
threshold3 = it;
|
|
@@ -132,12 +108,11 @@ function renyiEntropy(histogram, total) {
|
|
|
132
108
|
}
|
|
133
109
|
/* End Maximum Entropy Thresholding */
|
|
134
110
|
|
|
135
|
-
|
|
136
111
|
let tStars = [threshold1, threshold2, threshold3];
|
|
137
112
|
tStars.sort((a, b) => a - b);
|
|
138
113
|
let betas;
|
|
139
|
-
/* Adjust beta values */
|
|
140
114
|
|
|
115
|
+
/* Adjust beta values */
|
|
141
116
|
if (Math.abs(tStars[0] - tStars[1]) <= 5) {
|
|
142
117
|
if (Math.abs(tStars[1] - tStars[2]) <= 5) {
|
|
143
118
|
betas = [1, 2, 1];
|
|
@@ -151,9 +126,8 @@ function renyiEntropy(histogram, total) {
|
|
|
151
126
|
betas = [1, 2, 1];
|
|
152
127
|
}
|
|
153
128
|
}
|
|
154
|
-
/* Determine the optimal threshold value */
|
|
155
|
-
|
|
156
129
|
|
|
130
|
+
/* Determine the optimal threshold value */
|
|
157
131
|
let omega = P1[tStars[2]] - P1[tStars[0]];
|
|
158
132
|
optThreshold = Math.round(tStars[0] * (P1[tStars[0]] + 0.25 * omega * betas[0]) + 0.25 * tStars[1] * omega * betas[1] + tStars[2] * (P2[tStars[2]] + 0.25 * omega * betas[2]));
|
|
159
133
|
return optThreshold;
|
|
@@ -4,92 +4,75 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = shanbhag;
|
|
7
|
-
|
|
8
7
|
// see https://github.com/fiji/Auto_Threshold/blob/master/src/main/java/fiji/threshold/Auto_Threshold.java
|
|
9
8
|
// Shanhbag A.G. (1994) "Utilization of Information Measure as a Means of
|
|
10
9
|
// Image Thresholding" Graphical Models and Image Processing, 56(5): 414-419
|
|
11
10
|
// Ported to ImageJ plugin by G.Landini from E Celebi's fourier_0.8 routines
|
|
11
|
+
|
|
12
12
|
function shanbhag(histogram, total) {
|
|
13
13
|
let normHisto = new Array(histogram.length); // normalized histogram
|
|
14
|
-
|
|
15
14
|
for (let ih = 0; ih < histogram.length; ih++) {
|
|
16
15
|
normHisto[ih] = histogram[ih] / total;
|
|
17
16
|
}
|
|
18
|
-
|
|
19
17
|
let P1 = new Array(histogram.length); // cumulative normalized histogram
|
|
20
|
-
|
|
21
18
|
let P2 = new Array(histogram.length);
|
|
22
19
|
P1[0] = normHisto[0];
|
|
23
20
|
P2[0] = 1.0 - P1[0];
|
|
24
|
-
|
|
25
21
|
for (let ih = 1; ih < histogram.length; ih++) {
|
|
26
22
|
P1[ih] = P1[ih - 1] + normHisto[ih];
|
|
27
23
|
P2[ih] = 1.0 - P1[ih];
|
|
28
24
|
}
|
|
29
|
-
/* Determine the first non-zero bin */
|
|
30
|
-
|
|
31
25
|
|
|
26
|
+
/* Determine the first non-zero bin */
|
|
32
27
|
let firstBin = 0;
|
|
33
|
-
|
|
34
28
|
for (let ih = 0; ih < histogram.length; ih++) {
|
|
35
29
|
if (Math.abs(P1[ih]) >= Number.EPSILON) {
|
|
36
30
|
firstBin = ih;
|
|
37
31
|
break;
|
|
38
32
|
}
|
|
39
33
|
}
|
|
40
|
-
/* Determine the last non-zero bin */
|
|
41
|
-
|
|
42
34
|
|
|
35
|
+
/* Determine the last non-zero bin */
|
|
43
36
|
let lastBin = histogram.length - 1;
|
|
44
|
-
|
|
45
37
|
for (let ih = histogram.length - 1; ih >= firstBin; ih--) {
|
|
46
38
|
if (Math.abs(P2[ih]) >= Number.EPSILON) {
|
|
47
39
|
lastBin = ih;
|
|
48
40
|
break;
|
|
49
41
|
}
|
|
50
|
-
}
|
|
51
|
-
// and find the threshold that maximizes it
|
|
52
|
-
|
|
42
|
+
}
|
|
53
43
|
|
|
44
|
+
// Calculate the total entropy each gray-level
|
|
45
|
+
// and find the threshold that maximizes it
|
|
54
46
|
let threshold = -1;
|
|
55
47
|
let minEnt = Number.MAX_VALUE; // min entropy
|
|
56
48
|
|
|
57
49
|
let term;
|
|
58
50
|
let totEnt; // total entropy
|
|
59
|
-
|
|
60
51
|
let entBack; // entropy of the background pixels at a given threshold
|
|
61
|
-
|
|
62
52
|
let entObj; // entropy of the object pixels at a given threshold
|
|
63
|
-
|
|
64
53
|
for (let it = firstBin; it <= lastBin; it++) {
|
|
65
54
|
/* Entropy of the background pixels */
|
|
66
55
|
entBack = 0.0;
|
|
67
56
|
term = 0.5 / P1[it];
|
|
68
|
-
|
|
69
57
|
for (let ih = 1; ih <= it; ih++) {
|
|
70
58
|
entBack -= normHisto[ih] * Math.log(1.0 - term * P1[ih - 1]);
|
|
71
59
|
}
|
|
72
|
-
|
|
73
60
|
entBack *= term;
|
|
74
|
-
/* Entropy of the object pixels */
|
|
75
61
|
|
|
62
|
+
/* Entropy of the object pixels */
|
|
76
63
|
entObj = 0.0;
|
|
77
64
|
term = 0.5 / P2[it];
|
|
78
|
-
|
|
79
65
|
for (let ih = it + 1; ih < histogram.length; ih++) {
|
|
80
66
|
entObj -= normHisto[ih] * Math.log(1.0 - term * P2[ih]);
|
|
81
67
|
}
|
|
82
|
-
|
|
83
68
|
entObj *= term;
|
|
84
|
-
/* Total entropy */
|
|
85
69
|
|
|
70
|
+
/* Total entropy */
|
|
86
71
|
totEnt = Math.abs(entBack - entObj);
|
|
87
|
-
|
|
88
72
|
if (totEnt < minEnt) {
|
|
89
73
|
minEnt = totEnt;
|
|
90
74
|
threshold = it;
|
|
91
75
|
}
|
|
92
76
|
}
|
|
93
|
-
|
|
94
77
|
return threshold;
|
|
95
78
|
}
|
|
@@ -4,42 +4,26 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.names = exports.methods = void 0;
|
|
7
|
-
|
|
8
7
|
var _huang = _interopRequireDefault(require("./huang"));
|
|
9
|
-
|
|
10
8
|
var _intermodes = _interopRequireDefault(require("./intermodes"));
|
|
11
|
-
|
|
12
9
|
var _isodata = _interopRequireDefault(require("./isodata"));
|
|
13
|
-
|
|
14
10
|
var _li = _interopRequireDefault(require("./li"));
|
|
15
|
-
|
|
16
11
|
var _maxEntropy = _interopRequireDefault(require("./maxEntropy"));
|
|
17
|
-
|
|
18
12
|
var _mean = _interopRequireDefault(require("./mean"));
|
|
19
|
-
|
|
20
13
|
var _minError = _interopRequireDefault(require("./minError"));
|
|
21
|
-
|
|
22
14
|
var _minimum = _interopRequireDefault(require("./minimum"));
|
|
23
|
-
|
|
24
15
|
var _moments = _interopRequireDefault(require("./moments"));
|
|
25
|
-
|
|
26
16
|
var _otsu = _interopRequireDefault(require("./otsu"));
|
|
27
|
-
|
|
28
17
|
var _percentile = _interopRequireDefault(require("./percentile"));
|
|
29
|
-
|
|
30
18
|
var _renyiEntropy = _interopRequireDefault(require("./renyiEntropy.js"));
|
|
31
|
-
|
|
32
19
|
var _shanbhag = _interopRequireDefault(require("./shanbhag"));
|
|
33
|
-
|
|
34
20
|
var _triangle = _interopRequireDefault(require("./triangle"));
|
|
35
|
-
|
|
36
21
|
var _yen = _interopRequireDefault(require("./yen"));
|
|
37
|
-
|
|
38
22
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
39
|
-
|
|
40
23
|
/**
|
|
41
24
|
* @typedef {('huang'|'intermodes'|'isodata'|'li'|'maxentropy'|'mean'|'minerror'|'minimum'|'moments'|'otsu'|'percentile'|'renyientropy'|'shanbhag'|'triangle'|'yen')} ThresholdAlgorithm
|
|
42
25
|
*/
|
|
26
|
+
|
|
43
27
|
const methods = {
|
|
44
28
|
huang: _huang.default,
|
|
45
29
|
intermodes: _intermodes.default,
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = triangle;
|
|
7
|
-
|
|
8
7
|
// see https://github.com/fiji/Auto_Threshold/blob/master/src/main/java/fiji/threshold/Auto_Threshold.java
|
|
9
8
|
// Zack, G. W., Rogers, W. E. and Latt, S. A., 1977,
|
|
10
9
|
// Automatic Measurement of Sister Chromatid Exchange Frequency,
|
|
@@ -17,101 +16,87 @@ function triangle(histogram) {
|
|
|
17
16
|
let dmax = 0;
|
|
18
17
|
let max = 0;
|
|
19
18
|
let min2 = 0;
|
|
20
|
-
|
|
21
19
|
for (let i = 0; i < histogram.length; i++) {
|
|
22
20
|
if (histogram[i] > 0) {
|
|
23
21
|
min = i;
|
|
24
22
|
break;
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
|
-
|
|
28
25
|
if (min > 0) {
|
|
29
26
|
// line to the (p==0) point, not to histogram[min]
|
|
30
27
|
min--;
|
|
31
|
-
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// The Triangle algorithm cannot tell whether the data is skewed to one side or another.
|
|
32
31
|
// This causes a problem as there are 2 possible thresholds between the max and the 2 extremes
|
|
33
32
|
// of the histogram.
|
|
34
33
|
// Here I propose to find out to which side of the max point the data is furthest, and use that as
|
|
35
34
|
// the other extreme.
|
|
36
|
-
|
|
37
|
-
|
|
38
35
|
for (let i = histogram.length - 1; i > 0; i--) {
|
|
39
36
|
if (histogram[i] > 0) {
|
|
40
37
|
min2 = i;
|
|
41
38
|
break;
|
|
42
39
|
}
|
|
43
40
|
}
|
|
44
|
-
|
|
45
41
|
if (min2 < histogram.length - 1) {
|
|
46
42
|
// line to the (p==0) point, not to data[min]
|
|
47
43
|
min2++;
|
|
48
44
|
}
|
|
49
|
-
|
|
50
45
|
for (let i = 0; i < histogram.length; i++) {
|
|
51
46
|
if (histogram[i] > dmax) {
|
|
52
47
|
max = i;
|
|
53
48
|
dmax = histogram[i];
|
|
54
49
|
}
|
|
55
|
-
}
|
|
56
|
-
|
|
50
|
+
}
|
|
57
51
|
|
|
52
|
+
// find which is the furthest side
|
|
58
53
|
let inverted = false;
|
|
59
|
-
|
|
60
54
|
if (max - min < min2 - max) {
|
|
61
55
|
// reverse the histogram
|
|
62
56
|
inverted = true;
|
|
63
57
|
let left = 0; // index of leftmost element
|
|
64
|
-
|
|
65
58
|
let right = histogram.length - 1; // index of rightmost element
|
|
66
|
-
|
|
67
59
|
while (left < right) {
|
|
68
60
|
// exchange the left and right elements
|
|
69
61
|
let temp = histogram[left];
|
|
70
62
|
histogram[left] = histogram[right];
|
|
71
|
-
histogram[right] = temp;
|
|
72
|
-
|
|
63
|
+
histogram[right] = temp;
|
|
64
|
+
// move the bounds toward the center
|
|
73
65
|
left++;
|
|
74
66
|
right--;
|
|
75
67
|
}
|
|
76
|
-
|
|
77
68
|
min = histogram.length - 1 - min2;
|
|
78
69
|
max = histogram.length - 1 - max;
|
|
79
70
|
}
|
|
80
|
-
|
|
81
71
|
if (min === max) {
|
|
82
72
|
return min;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
let nx, ny, d; // nx is just the max frequency as the other point has freq=0
|
|
73
|
+
}
|
|
87
74
|
|
|
75
|
+
// describe line by nx * x + ny * y - d = 0
|
|
76
|
+
let nx, ny, d;
|
|
77
|
+
// nx is just the max frequency as the other point has freq=0
|
|
88
78
|
nx = histogram[max]; // -min; // data[min]; // lowest value bmin = (p=0)% in the image
|
|
89
|
-
|
|
90
79
|
ny = min - max;
|
|
91
80
|
d = Math.sqrt(nx * nx + ny * ny);
|
|
92
81
|
nx /= d;
|
|
93
82
|
ny /= d;
|
|
94
|
-
d = nx * min + ny * histogram[min];
|
|
83
|
+
d = nx * min + ny * histogram[min];
|
|
95
84
|
|
|
85
|
+
// find split point
|
|
96
86
|
let split = min;
|
|
97
87
|
let splitDistance = 0;
|
|
98
|
-
|
|
99
88
|
for (let i = min + 1; i <= max; i++) {
|
|
100
89
|
let newDistance = nx * i + ny * histogram[i] - d;
|
|
101
|
-
|
|
102
90
|
if (newDistance > splitDistance) {
|
|
103
91
|
split = i;
|
|
104
92
|
splitDistance = newDistance;
|
|
105
93
|
}
|
|
106
94
|
}
|
|
107
|
-
|
|
108
95
|
split--;
|
|
109
|
-
|
|
110
96
|
if (inverted) {
|
|
111
97
|
// The histogram might be used for something else, so let's reverse it back
|
|
112
98
|
let left = 0;
|
|
113
99
|
let right = histogram.length - 1;
|
|
114
|
-
|
|
115
100
|
while (left < right) {
|
|
116
101
|
let temp = histogram[left];
|
|
117
102
|
histogram[left] = histogram[right];
|
|
@@ -119,7 +104,6 @@ function triangle(histogram) {
|
|
|
119
104
|
left++;
|
|
120
105
|
right--;
|
|
121
106
|
}
|
|
122
|
-
|
|
123
107
|
return histogram.length - 1 - split;
|
|
124
108
|
} else {
|
|
125
109
|
return split;
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = yen;
|
|
7
|
-
|
|
8
7
|
// see https://github.com/fiji/Auto_Threshold/blob/master/src/main/java/fiji/threshold/Auto_Threshold.java
|
|
9
8
|
// Implements Yen thresholding method
|
|
10
9
|
// 1) Yen J.C., Chang F.J., and Chang S. (1995) "A New Criterion
|
|
@@ -18,49 +17,38 @@ exports.default = yen;
|
|
|
18
17
|
// M. Emre Celebi
|
|
19
18
|
// 06.15.2007
|
|
20
19
|
// Ported to ImageJ plugin by G.Landini from E Celebi's fourier_0.8 routines
|
|
20
|
+
|
|
21
21
|
function yen(histogram, total) {
|
|
22
22
|
let normHisto = new Array(histogram.length); // normalized histogram
|
|
23
|
-
|
|
24
23
|
for (let ih = 0; ih < histogram.length; ih++) {
|
|
25
24
|
normHisto[ih] = histogram[ih] / total;
|
|
26
25
|
}
|
|
27
|
-
|
|
28
26
|
let P1 = new Array(histogram.length); // cumulative normalized histogram
|
|
29
|
-
|
|
30
27
|
P1[0] = normHisto[0];
|
|
31
|
-
|
|
32
28
|
for (let ih = 1; ih < histogram.length; ih++) {
|
|
33
29
|
P1[ih] = P1[ih - 1] + normHisto[ih];
|
|
34
30
|
}
|
|
35
|
-
|
|
36
31
|
let P1Sq = new Array(histogram.length);
|
|
37
32
|
P1Sq[0] = normHisto[0] * normHisto[0];
|
|
38
|
-
|
|
39
33
|
for (let ih = 1; ih < histogram.length; ih++) {
|
|
40
34
|
P1Sq[ih] = P1Sq[ih - 1] + normHisto[ih] * normHisto[ih];
|
|
41
35
|
}
|
|
42
|
-
|
|
43
36
|
let P2Sq = new Array(histogram.length);
|
|
44
37
|
P2Sq[histogram.length - 1] = 0.0;
|
|
45
|
-
|
|
46
38
|
for (let ih = histogram.length - 2; ih >= 0; ih--) {
|
|
47
39
|
P2Sq[ih] = P2Sq[ih + 1] + normHisto[ih + 1] * normHisto[ih + 1];
|
|
48
40
|
}
|
|
49
|
-
/* Find the threshold that maximizes the criterion */
|
|
50
|
-
|
|
51
41
|
|
|
42
|
+
/* Find the threshold that maximizes the criterion */
|
|
52
43
|
let threshold = -1;
|
|
53
44
|
let maxCrit = Number.MIN_VALUE;
|
|
54
45
|
let crit;
|
|
55
|
-
|
|
56
46
|
for (let it = 0; it < histogram.length; it++) {
|
|
57
47
|
crit = -1.0 * (P1Sq[it] * P2Sq[it] > 0.0 ? Math.log(P1Sq[it] * P2Sq[it]) : 0.0) + 2 * (P1[it] * (1.0 - P1[it]) > 0.0 ? Math.log(P1[it] * (1.0 - P1[it])) : 0.0);
|
|
58
|
-
|
|
59
48
|
if (crit > maxCrit) {
|
|
60
49
|
maxCrit = crit;
|
|
61
50
|
threshold = it;
|
|
62
51
|
}
|
|
63
52
|
}
|
|
64
|
-
|
|
65
53
|
return threshold;
|
|
66
54
|
}
|
|
@@ -4,15 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = pad;
|
|
7
|
-
|
|
8
7
|
var _newArray = _interopRequireDefault(require("new-array"));
|
|
9
|
-
|
|
10
8
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
11
|
-
|
|
12
9
|
var _copy = _interopRequireDefault(require("../internal/copy"));
|
|
13
|
-
|
|
14
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
-
|
|
16
11
|
/**
|
|
17
12
|
* @memberof Image
|
|
18
13
|
* @instance
|
|
@@ -31,12 +26,10 @@ function pad(options = {}) {
|
|
|
31
26
|
this.checkProcessable('pad', {
|
|
32
27
|
bitDepth: [8, 16]
|
|
33
28
|
});
|
|
34
|
-
|
|
35
29
|
if (algorithm === 'set') {
|
|
36
30
|
if (color.length !== this.channels) {
|
|
37
31
|
throw new Error(`pad: the color array must have the same length as the number of channels. Here: ${this.channels}`);
|
|
38
32
|
}
|
|
39
|
-
|
|
40
33
|
for (let i = 0; i < color.length; i++) {
|
|
41
34
|
if (color[i] === 0) {
|
|
42
35
|
color[i] = 0.001;
|
|
@@ -45,53 +38,40 @@ function pad(options = {}) {
|
|
|
45
38
|
} else {
|
|
46
39
|
color = (0, _newArray.default)(this.channels, null);
|
|
47
40
|
}
|
|
48
|
-
|
|
49
41
|
if (!Array.isArray(size)) {
|
|
50
42
|
size = [size, size];
|
|
51
43
|
}
|
|
52
|
-
|
|
53
44
|
let newWidth = this.width + size[0] * 2;
|
|
54
45
|
let newHeight = this.height + size[1] * 2;
|
|
55
46
|
let channels = this.channels;
|
|
56
|
-
|
|
57
47
|
let newImage = _Image.default.createFrom(this, {
|
|
58
48
|
width: newWidth,
|
|
59
49
|
height: newHeight
|
|
60
50
|
});
|
|
61
|
-
|
|
62
51
|
(0, _copy.default)(this, newImage, size[0], size[1]);
|
|
63
|
-
|
|
64
52
|
for (let i = size[0]; i < newWidth - size[0]; i++) {
|
|
65
53
|
for (let k = 0; k < channels; k++) {
|
|
66
54
|
let value = color[k] || newImage.data[(size[1] * newWidth + i) * channels + k];
|
|
67
|
-
|
|
68
55
|
for (let j = 0; j < size[1]; j++) {
|
|
69
56
|
newImage.data[(j * newWidth + i) * channels + k] = value;
|
|
70
57
|
}
|
|
71
|
-
|
|
72
58
|
value = color[k] || newImage.data[((newHeight - size[1] - 1) * newWidth + i) * channels + k];
|
|
73
|
-
|
|
74
59
|
for (let j = newHeight - size[1]; j < newHeight; j++) {
|
|
75
60
|
newImage.data[(j * newWidth + i) * channels + k] = value;
|
|
76
61
|
}
|
|
77
62
|
}
|
|
78
63
|
}
|
|
79
|
-
|
|
80
64
|
for (let j = 0; j < newHeight; j++) {
|
|
81
65
|
for (let k = 0; k < channels; k++) {
|
|
82
66
|
let value = color[k] || newImage.data[(j * newWidth + size[0]) * channels + k];
|
|
83
|
-
|
|
84
67
|
for (let i = 0; i < size[0]; i++) {
|
|
85
68
|
newImage.data[(j * newWidth + i) * channels + k] = value;
|
|
86
69
|
}
|
|
87
|
-
|
|
88
70
|
value = color[k] || newImage.data[(j * newWidth + newWidth - size[0] - 1) * channels + k];
|
|
89
|
-
|
|
90
71
|
for (let i = newWidth - size[0]; i < newWidth; i++) {
|
|
91
72
|
newImage.data[(j * newWidth + i) * channels + k] = value;
|
|
92
73
|
}
|
|
93
74
|
}
|
|
94
75
|
}
|
|
95
|
-
|
|
96
76
|
return newImage;
|
|
97
77
|
}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = nearestNeighbor;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* Nearest neighbor resizing algorithm
|
|
10
9
|
* @private
|
|
@@ -15,14 +14,11 @@ exports.default = nearestNeighbor;
|
|
|
15
14
|
function nearestNeighbor(newImage, newWidth, newHeight) {
|
|
16
15
|
const wRatio = this.width / newWidth;
|
|
17
16
|
const hRatio = this.height / newHeight;
|
|
18
|
-
|
|
19
17
|
if (this.bitDepth > 1) {
|
|
20
18
|
for (let i = 0; i < newWidth; i++) {
|
|
21
19
|
const w = Math.floor((i + 0.5) * wRatio);
|
|
22
|
-
|
|
23
20
|
for (let j = 0; j < newHeight; j++) {
|
|
24
21
|
const h = Math.floor((j + 0.5) * hRatio);
|
|
25
|
-
|
|
26
22
|
for (let c = 0; c < this.channels; c++) {
|
|
27
23
|
newImage.setValueXY(i, j, c, this.getValueXY(w, h, c));
|
|
28
24
|
}
|
|
@@ -31,10 +27,8 @@ function nearestNeighbor(newImage, newWidth, newHeight) {
|
|
|
31
27
|
} else {
|
|
32
28
|
for (let i = 0; i < newWidth; i++) {
|
|
33
29
|
const w = Math.floor((i + 0.5) * wRatio);
|
|
34
|
-
|
|
35
30
|
for (let j = 0; j < newHeight; j++) {
|
|
36
31
|
const h = Math.floor((j + 0.5) * hRatio);
|
|
37
|
-
|
|
38
32
|
if (this.getBitXY(w, h)) {
|
|
39
33
|
newImage.setBitXY(i, j);
|
|
40
34
|
}
|