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,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = extendedPoints;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* Allows to generate an array of points for a binary image (bit depth = 1)
|
|
10
9
|
* The points consider the beginning and the end of each pixel
|
|
@@ -18,16 +17,13 @@ function extendedPoints() {
|
|
|
18
17
|
bitDepth: [1]
|
|
19
18
|
});
|
|
20
19
|
const pixels = [];
|
|
21
|
-
|
|
22
20
|
for (let y = 0; y < this.height; y++) {
|
|
23
21
|
for (let x = 0; x < this.width; x++) {
|
|
24
22
|
if (this.getBitXY(x, y) === 1) {
|
|
25
23
|
pixels.push([x, y]);
|
|
26
|
-
|
|
27
24
|
if (this.getBitXY(x + 1, y) !== 1) {
|
|
28
25
|
pixels.push([x + 1, y]);
|
|
29
26
|
pixels.push([x + 1, y + 1]);
|
|
30
|
-
|
|
31
27
|
if (this.getBitXY(x, y + 1) !== 1) {
|
|
32
28
|
pixels.push([x, y + 1]);
|
|
33
29
|
}
|
|
@@ -36,15 +32,14 @@ function extendedPoints() {
|
|
|
36
32
|
pixels.push([x, y + 1]);
|
|
37
33
|
pixels.push([x + 1, y + 1]);
|
|
38
34
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
35
|
+
}
|
|
41
36
|
|
|
37
|
+
// this small optimization allows to reduce dramatically the number of points for MBR calculation
|
|
42
38
|
while (x < this.width - 2 && this.getBitXY(x + 1, y) === 1 && this.getBitXY(x + 2, y) === 1) {
|
|
43
39
|
x++;
|
|
44
40
|
}
|
|
45
41
|
}
|
|
46
42
|
}
|
|
47
43
|
}
|
|
48
|
-
|
|
49
44
|
return pixels;
|
|
50
45
|
}
|
|
@@ -5,13 +5,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.getHistogram = getHistogram;
|
|
7
7
|
exports.getHistograms = getHistograms;
|
|
8
|
-
|
|
9
8
|
var _isInteger = _interopRequireDefault(require("is-integer"));
|
|
10
|
-
|
|
11
9
|
var _newArray = _interopRequireDefault(require("new-array"));
|
|
12
|
-
|
|
13
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
|
-
|
|
15
11
|
/**
|
|
16
12
|
* Returns a histogram for the specified channel
|
|
17
13
|
* @memberof Image
|
|
@@ -31,20 +27,18 @@ function getHistogram(options = {}) {
|
|
|
31
27
|
this.checkProcessable('getHistogram', {
|
|
32
28
|
bitDepth: [1, 8, 16]
|
|
33
29
|
});
|
|
34
|
-
|
|
35
30
|
if (channel === undefined) {
|
|
36
31
|
if (this.components > 1) {
|
|
37
32
|
throw new RangeError('You need to define the channel for an image that contains more than one channel');
|
|
38
33
|
}
|
|
39
|
-
|
|
40
34
|
channel = 0;
|
|
41
35
|
}
|
|
42
|
-
|
|
43
36
|
return getChannelHistogram.call(this, channel, {
|
|
44
37
|
useAlpha,
|
|
45
38
|
maxSlots
|
|
46
39
|
});
|
|
47
40
|
}
|
|
41
|
+
|
|
48
42
|
/**
|
|
49
43
|
* Returns an array (number of channels) of array (number of slots) containing
|
|
50
44
|
* the number of data of a specific intensity.
|
|
@@ -64,8 +58,6 @@ function getHistogram(options = {}) {
|
|
|
64
58
|
* useAlpha: false
|
|
65
59
|
* });
|
|
66
60
|
*/
|
|
67
|
-
|
|
68
|
-
|
|
69
61
|
function getHistograms(options = {}) {
|
|
70
62
|
const {
|
|
71
63
|
maxSlots = 256,
|
|
@@ -75,30 +67,27 @@ function getHistograms(options = {}) {
|
|
|
75
67
|
bitDepth: [8, 16]
|
|
76
68
|
});
|
|
77
69
|
let results = new Array(useAlpha ? this.components : this.channels);
|
|
78
|
-
|
|
79
70
|
for (let i = 0; i < results.length; i++) {
|
|
80
71
|
results[i] = getChannelHistogram.call(this, i, {
|
|
81
72
|
useAlpha,
|
|
82
73
|
maxSlots
|
|
83
74
|
});
|
|
84
75
|
}
|
|
85
|
-
|
|
86
76
|
return results;
|
|
87
77
|
}
|
|
88
|
-
|
|
89
78
|
function getChannelHistogram(channel, options) {
|
|
90
79
|
let {
|
|
91
80
|
useAlpha,
|
|
92
81
|
maxSlots
|
|
93
|
-
} = options;
|
|
82
|
+
} = options;
|
|
83
|
+
|
|
84
|
+
// for a mask, return a number array containing count of black and white points (black = array[0], white = array[1])
|
|
94
85
|
|
|
95
86
|
if (this.bitDepth === 1) {
|
|
96
87
|
let blackWhiteCount = [0, 0];
|
|
97
|
-
|
|
98
88
|
for (let i = 0; i < this.height; i++) {
|
|
99
89
|
for (let j = 0; j < this.width; j++) {
|
|
100
90
|
let value = this.getBitXY(i, j);
|
|
101
|
-
|
|
102
91
|
if (value === 0) {
|
|
103
92
|
blackWhiteCount[0] += 1;
|
|
104
93
|
} else if (value === 1) {
|
|
@@ -106,31 +95,24 @@ function getChannelHistogram(channel, options) {
|
|
|
106
95
|
}
|
|
107
96
|
}
|
|
108
97
|
}
|
|
109
|
-
|
|
110
98
|
return blackWhiteCount;
|
|
111
99
|
}
|
|
112
|
-
|
|
113
100
|
let bitSlots = Math.log2(maxSlots);
|
|
114
|
-
|
|
115
101
|
if (!(0, _isInteger.default)(bitSlots)) {
|
|
116
102
|
throw new RangeError('maxSlots must be a power of 2, for example: 64, 256, 1024');
|
|
117
|
-
}
|
|
103
|
+
}
|
|
104
|
+
// we will compare the bitSlots to the bitDepth of the image
|
|
118
105
|
// based on this we will shift the values. This allows to generate a histogram
|
|
119
106
|
// of 16 grey even if the images has 256 shade of grey
|
|
120
107
|
|
|
121
|
-
|
|
122
108
|
let bitShift = 0;
|
|
123
|
-
|
|
124
109
|
if (this.bitDepth > bitSlots) {
|
|
125
110
|
bitShift = this.bitDepth - bitSlots;
|
|
126
111
|
}
|
|
127
|
-
|
|
128
112
|
let data = this.data;
|
|
129
113
|
let result = (0, _newArray.default)(Math.pow(2, Math.min(this.bitDepth, bitSlots)), 0);
|
|
130
|
-
|
|
131
114
|
if (useAlpha && this.alpha) {
|
|
132
115
|
let alphaChannelDiff = this.channels - channel - 1;
|
|
133
|
-
|
|
134
116
|
for (let i = channel; i < data.length; i += this.channels) {
|
|
135
117
|
result[data[i] >> bitShift] += data[i + alphaChannelDiff] / this.maxValue;
|
|
136
118
|
}
|
|
@@ -139,6 +121,5 @@ function getChannelHistogram(channel, options) {
|
|
|
139
121
|
result[data[i] >> bitShift]++;
|
|
140
122
|
}
|
|
141
123
|
}
|
|
142
|
-
|
|
143
124
|
return result;
|
|
144
125
|
}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = localMaxima;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* Returns an array of object with position.
|
|
10
9
|
* @memberof Image
|
|
@@ -37,17 +36,14 @@ function localMaxima(options = {}) {
|
|
|
37
36
|
let dy = [0, +1, 0, -1, +1, -1, +1, -1, 0, +2, 0, -2, +2, -2, +2, -2];
|
|
38
37
|
let shift = region <= 8 ? 1 : 2;
|
|
39
38
|
let points = [];
|
|
40
|
-
|
|
41
39
|
for (let currentY = shift; currentY < image.height - shift; currentY++) {
|
|
42
40
|
for (let currentX = shift; currentX < image.width - shift; currentX++) {
|
|
43
41
|
if (mask && mask.getBitXY(currentX, currentY) !== maskExpectedValue) {
|
|
44
42
|
continue;
|
|
45
43
|
}
|
|
46
|
-
|
|
47
44
|
let counter = 0;
|
|
48
45
|
let nbEquals = 0;
|
|
49
46
|
let currentValue = image.data[currentX + currentY * image.width];
|
|
50
|
-
|
|
51
47
|
for (let dir = 0; dir < region; dir++) {
|
|
52
48
|
if (invert) {
|
|
53
49
|
// we search for minima
|
|
@@ -59,24 +55,21 @@ function localMaxima(options = {}) {
|
|
|
59
55
|
counter++;
|
|
60
56
|
}
|
|
61
57
|
}
|
|
62
|
-
|
|
63
58
|
if (image.data[currentX + dx[dir] + (currentY + dy[dir]) * image.width] === currentValue) {
|
|
64
59
|
nbEquals++;
|
|
65
60
|
}
|
|
66
61
|
}
|
|
67
|
-
|
|
68
62
|
if (counter + nbEquals === region && nbEquals <= maxEquals) {
|
|
69
63
|
points.push([currentX, currentY]);
|
|
70
64
|
}
|
|
71
65
|
}
|
|
72
|
-
}
|
|
66
|
+
}
|
|
67
|
+
// TODO How to make a more performant and general way
|
|
73
68
|
// we don't deal correctly here with groups of points that should be grouped if at the
|
|
74
69
|
// beginning one of them is closer to another
|
|
75
70
|
// Seems that we would ened to calculate a matrix and then split this matrix in 'independant matrices'
|
|
76
71
|
// Or to assign a cluster to each point and regroup them if 2 clusters are close to each other
|
|
77
72
|
// later approach seems much better
|
|
78
|
-
|
|
79
|
-
|
|
80
73
|
if (removeClosePoints > 0) {
|
|
81
74
|
for (let i = 0; i < points.length; i++) {
|
|
82
75
|
for (let j = i + 1; j < points.length; j++) {
|
|
@@ -89,6 +82,5 @@ function localMaxima(options = {}) {
|
|
|
89
82
|
}
|
|
90
83
|
}
|
|
91
84
|
}
|
|
92
|
-
|
|
93
85
|
return points;
|
|
94
86
|
}
|
package/lib/image/compute/max.js
CHANGED
|
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = max;
|
|
7
|
-
|
|
8
7
|
var _newArray = _interopRequireDefault(require("new-array"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* Returns an array with the maximal value of each channel
|
|
14
11
|
* @memberof Image
|
|
@@ -20,7 +17,6 @@ function max() {
|
|
|
20
17
|
bitDepth: [8, 16, 32]
|
|
21
18
|
});
|
|
22
19
|
let result = (0, _newArray.default)(this.channels, -Infinity);
|
|
23
|
-
|
|
24
20
|
for (let i = 0; i < this.data.length; i += this.channels) {
|
|
25
21
|
for (let c = 0; c < this.channels; c++) {
|
|
26
22
|
if (this.data[i + c] > result[c]) {
|
|
@@ -28,6 +24,5 @@ function max() {
|
|
|
28
24
|
}
|
|
29
25
|
}
|
|
30
26
|
}
|
|
31
|
-
|
|
32
27
|
return result;
|
|
33
28
|
}
|
|
@@ -4,9 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = mean;
|
|
7
|
-
|
|
8
7
|
var _histogram = require("../../util/histogram");
|
|
9
|
-
|
|
10
8
|
/**
|
|
11
9
|
* Returns an array with the average value of each channel
|
|
12
10
|
* @memberof Image
|
|
@@ -18,11 +16,9 @@ function mean() {
|
|
|
18
16
|
maxSlots: this.maxValue + 1
|
|
19
17
|
});
|
|
20
18
|
let result = new Array(histograms.length);
|
|
21
|
-
|
|
22
19
|
for (let c = 0; c < histograms.length; c++) {
|
|
23
20
|
let histogram = histograms[c];
|
|
24
21
|
result[c] = (0, _histogram.mean)(histogram);
|
|
25
22
|
}
|
|
26
|
-
|
|
27
23
|
return result;
|
|
28
24
|
}
|
|
@@ -4,9 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = median;
|
|
7
|
-
|
|
8
7
|
var _histogram = require("../../util/histogram");
|
|
9
|
-
|
|
10
8
|
/**
|
|
11
9
|
* Returns an array with the median value of each channel
|
|
12
10
|
* @memberof Image
|
|
@@ -18,11 +16,9 @@ function median() {
|
|
|
18
16
|
maxSlots: this.maxValue + 1
|
|
19
17
|
});
|
|
20
18
|
let result = new Array(histograms.length);
|
|
21
|
-
|
|
22
19
|
for (let c = 0; c < histograms.length; c++) {
|
|
23
20
|
let histogram = histograms[c];
|
|
24
21
|
result[c] = (0, _histogram.median)(histogram);
|
|
25
22
|
}
|
|
26
|
-
|
|
27
23
|
return result;
|
|
28
24
|
}
|
package/lib/image/compute/min.js
CHANGED
|
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = min;
|
|
7
|
-
|
|
8
7
|
var _newArray = _interopRequireDefault(require("new-array"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* Returns an array with the minimal value of each channel
|
|
14
11
|
* @memberof Image
|
|
@@ -20,7 +17,6 @@ function min() {
|
|
|
20
17
|
bitDepth: [8, 16, 32]
|
|
21
18
|
});
|
|
22
19
|
let result = (0, _newArray.default)(this.channels, +Infinity);
|
|
23
|
-
|
|
24
20
|
for (let i = 0; i < this.data.length; i += this.channels) {
|
|
25
21
|
for (let c = 0; c < this.channels; c++) {
|
|
26
22
|
if (this.data[i + c] < result[c]) {
|
|
@@ -28,6 +24,5 @@ function min() {
|
|
|
28
24
|
}
|
|
29
25
|
}
|
|
30
26
|
}
|
|
31
|
-
|
|
32
27
|
return result;
|
|
33
28
|
}
|
|
@@ -4,13 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = minimalBoundingRectangle;
|
|
7
|
-
|
|
8
7
|
var _points = require("../../util/points");
|
|
9
|
-
|
|
10
8
|
var _monotoneChainConvexHull = _interopRequireDefault(require("./monotoneChainConvexHull"));
|
|
11
|
-
|
|
12
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
|
|
14
10
|
/**
|
|
15
11
|
* Computes the minimum bounding box around a binary image
|
|
16
12
|
* https://www.researchgate.net/profile/Lennert_Den_Boer2/publication/303783472_A_Fast_Algorithm_for_Generating_a_Minimal_Bounding_Rectangle/links/5751a14108ae6807fafb2aa5.pdf
|
|
@@ -24,24 +20,21 @@ function minimalBoundingRectangle(options = {}) {
|
|
|
24
20
|
const {
|
|
25
21
|
originalPoints = _monotoneChainConvexHull.default.call(this)
|
|
26
22
|
} = options;
|
|
27
|
-
|
|
28
23
|
if (originalPoints.length === 0) {
|
|
29
24
|
return [];
|
|
30
25
|
}
|
|
31
|
-
|
|
32
26
|
if (originalPoints.length === 1) {
|
|
33
27
|
return [originalPoints[0], originalPoints[0], originalPoints[0], originalPoints[0]];
|
|
34
28
|
}
|
|
35
|
-
|
|
36
29
|
const p = new Array(originalPoints.length);
|
|
37
30
|
let minSurface = +Infinity;
|
|
38
31
|
let minSurfaceAngle = 0;
|
|
39
32
|
let mbr;
|
|
40
|
-
|
|
41
33
|
for (let i = 0; i < p.length; i++) {
|
|
42
34
|
let angle = getAngle(originalPoints[i], originalPoints[(i + 1) % p.length]);
|
|
43
|
-
(0, _points.rotate)(-angle, originalPoints, p);
|
|
35
|
+
(0, _points.rotate)(-angle, originalPoints, p);
|
|
44
36
|
|
|
37
|
+
// we rotate and translate so that this axe is in the bottom
|
|
45
38
|
let aX = p[i][0];
|
|
46
39
|
let aY = p[i][1];
|
|
47
40
|
let bX = p[(i + 1) % p.length][0];
|
|
@@ -50,12 +43,10 @@ function minimalBoundingRectangle(options = {}) {
|
|
|
50
43
|
let tMin = 0;
|
|
51
44
|
let tMax = 0;
|
|
52
45
|
let maxWidth = 0;
|
|
53
|
-
|
|
54
46
|
for (let j = 0; j < p.length; j++) {
|
|
55
47
|
let cX = p[j][0];
|
|
56
48
|
let cY = p[j][1];
|
|
57
49
|
let t = (cX - aX) / (bX - aX);
|
|
58
|
-
|
|
59
50
|
if (tUndefined === true) {
|
|
60
51
|
tUndefined = false;
|
|
61
52
|
tMin = t;
|
|
@@ -64,28 +55,24 @@ function minimalBoundingRectangle(options = {}) {
|
|
|
64
55
|
if (t < tMin) tMin = t;
|
|
65
56
|
if (t > tMax) tMax = t;
|
|
66
57
|
}
|
|
67
|
-
|
|
68
58
|
let width = (-(bX - aX) * cY + bX * aY - bY * aX) / (bX - aX);
|
|
69
59
|
if (Math.abs(width) > Math.abs(maxWidth)) maxWidth = width;
|
|
70
60
|
}
|
|
71
|
-
|
|
72
61
|
let pMin = [aX + tMin * (bX - aX), aY];
|
|
73
62
|
let pMax = [aX + tMax * (bX - aX), aY];
|
|
74
63
|
let currentSurface = Math.abs(maxWidth * (tMin - tMax) * (bX - aX));
|
|
75
|
-
|
|
76
64
|
if (currentSurface < minSurface) {
|
|
77
65
|
minSurfaceAngle = angle;
|
|
78
66
|
minSurface = currentSurface;
|
|
79
67
|
mbr = [pMin, pMax, [pMax[0], pMax[1] - maxWidth], [pMin[0], pMin[1] - maxWidth]];
|
|
80
68
|
}
|
|
81
69
|
}
|
|
82
|
-
|
|
83
70
|
(0, _points.rotate)(minSurfaceAngle, mbr, mbr);
|
|
84
71
|
return mbr;
|
|
85
|
-
}
|
|
86
|
-
// this is an optimized version because it assume one vector is horizontal
|
|
87
|
-
|
|
72
|
+
}
|
|
88
73
|
|
|
74
|
+
// the angle that allows to make the line going through p1 and p2 horizontal
|
|
75
|
+
// this is an optimized version because it assume one vector is horizontal
|
|
89
76
|
function getAngle(p1, p2) {
|
|
90
77
|
let diff = (0, _points.difference)(p2, p1);
|
|
91
78
|
let vector = (0, _points.normalize)(diff);
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = getMoment;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* Returns the moment of an image (https://en.wikipedia.org/wiki/Image_moment)
|
|
10
9
|
* @memberof Image
|
|
@@ -18,7 +17,6 @@ function getMoment(xPower = 0, yPower = 0) {
|
|
|
18
17
|
bitDepth: [1]
|
|
19
18
|
});
|
|
20
19
|
let m = 0;
|
|
21
|
-
|
|
22
20
|
for (let x = 0; x < this.width; x++) {
|
|
23
21
|
for (let y = 0; y < this.height; y++) {
|
|
24
22
|
if (this.getBitXY(x, y) === 1) {
|
|
@@ -26,6 +24,5 @@ function getMoment(xPower = 0, yPower = 0) {
|
|
|
26
24
|
}
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
|
-
|
|
30
27
|
return m;
|
|
31
28
|
}
|
|
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = monotoneChainConvexHull;
|
|
7
|
-
|
|
8
7
|
var _monotoneChainConvexHull = _interopRequireDefault(require("monotone-chain-convex-hull"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* Returns the convex hull of a binary image
|
|
14
11
|
* @memberof Image
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = points;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* Allows to generate an array of points for a binary image (bit depth = 1)
|
|
10
9
|
* @memberof Image
|
|
@@ -16,7 +15,6 @@ function points() {
|
|
|
16
15
|
bitDepth: [1]
|
|
17
16
|
});
|
|
18
17
|
const pixels = [];
|
|
19
|
-
|
|
20
18
|
for (let x = 0; x < this.width; x++) {
|
|
21
19
|
for (let y = 0; y < this.height; y++) {
|
|
22
20
|
if (this.getBitXY(x, y) === 1) {
|
|
@@ -24,6 +22,5 @@ function points() {
|
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
|
-
|
|
28
25
|
return pixels;
|
|
29
26
|
}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = getRelativePosition;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* An image may be derived from another image either by a crop
|
|
10
9
|
* or because it is a ROI (region of interest)
|
|
@@ -26,25 +25,20 @@ function getRelativePosition(targetImage, options = {}) {
|
|
|
26
25
|
if (this === targetImage) {
|
|
27
26
|
return [0, 0];
|
|
28
27
|
}
|
|
29
|
-
|
|
30
28
|
let position = [0, 0];
|
|
31
29
|
let currentImage = this;
|
|
32
|
-
|
|
33
30
|
while (currentImage) {
|
|
34
31
|
if (currentImage === targetImage) {
|
|
35
32
|
return position;
|
|
36
33
|
}
|
|
37
|
-
|
|
38
34
|
if (currentImage.position) {
|
|
39
35
|
position[0] += currentImage.position[0];
|
|
40
36
|
position[1] += currentImage.position[1];
|
|
41
37
|
}
|
|
42
|
-
|
|
43
38
|
currentImage = currentImage.parent;
|
|
44
|
-
}
|
|
39
|
+
}
|
|
40
|
+
// we should never reach this place, this means we could not find the parent
|
|
45
41
|
// throw Error('Parent image was not found, can not get relative position.')
|
|
46
|
-
|
|
47
|
-
|
|
48
42
|
if (options.defaultFurther) return position;
|
|
49
43
|
return false;
|
|
50
44
|
}
|
package/lib/image/compute/sum.js
CHANGED
|
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = sum;
|
|
7
|
-
|
|
8
7
|
var _newArray = _interopRequireDefault(require("new-array"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* Returns an array with the sum of the values of each channel
|
|
14
11
|
* @memberof Image
|
|
@@ -20,12 +17,10 @@ function sum() {
|
|
|
20
17
|
bitDepth: [8, 16]
|
|
21
18
|
});
|
|
22
19
|
let result = (0, _newArray.default)(this.channels, 0);
|
|
23
|
-
|
|
24
20
|
for (let i = 0; i < this.data.length; i += this.channels) {
|
|
25
21
|
for (let c = 0; c < this.channels; c++) {
|
|
26
22
|
result[c] += this.data[i + c];
|
|
27
23
|
}
|
|
28
24
|
}
|
|
29
|
-
|
|
30
25
|
return result;
|
|
31
26
|
}
|
|
@@ -17,7 +17,6 @@ const bitMethods = {
|
|
|
17
17
|
getBit(pixel) {
|
|
18
18
|
return this.data[getSlot(pixel)] & 1 << getShift(pixel) ? 1 : 0;
|
|
19
19
|
},
|
|
20
|
-
|
|
21
20
|
/**
|
|
22
21
|
* Set the bit of a pixel using a pixel index.
|
|
23
22
|
* This method can only be called on binary images.
|
|
@@ -28,7 +27,6 @@ const bitMethods = {
|
|
|
28
27
|
setBit(pixel) {
|
|
29
28
|
this.data[getSlot(pixel)] |= 1 << getShift(pixel);
|
|
30
29
|
},
|
|
31
|
-
|
|
32
30
|
/**
|
|
33
31
|
* Clear the bit of a pixel using a pixel index.
|
|
34
32
|
* This method can only be called on binary images.
|
|
@@ -39,7 +37,6 @@ const bitMethods = {
|
|
|
39
37
|
clearBit(pixel) {
|
|
40
38
|
this.data[getSlot(pixel)] &= ~(1 << getShift(pixel));
|
|
41
39
|
},
|
|
42
|
-
|
|
43
40
|
/**
|
|
44
41
|
* Toggle (invert) the bit of a pixel using a pixel index.
|
|
45
42
|
* This method can only be called on binary images.
|
|
@@ -50,7 +47,6 @@ const bitMethods = {
|
|
|
50
47
|
toggleBit(pixel) {
|
|
51
48
|
this.data[getSlot(pixel)] ^= 1 << getShift(pixel);
|
|
52
49
|
},
|
|
53
|
-
|
|
54
50
|
/**
|
|
55
51
|
* Get the bit of a pixel using coordinates.
|
|
56
52
|
* This method can only be called on binary images.
|
|
@@ -64,7 +60,6 @@ const bitMethods = {
|
|
|
64
60
|
if (x >= this.width || y >= this.height) return 0;
|
|
65
61
|
return this.getBit(y * this.width + x);
|
|
66
62
|
},
|
|
67
|
-
|
|
68
63
|
/**
|
|
69
64
|
* Set the bit of a pixel using coordinates.
|
|
70
65
|
* This method can only be called on binary images.
|
|
@@ -76,7 +71,6 @@ const bitMethods = {
|
|
|
76
71
|
setBitXY(x, y) {
|
|
77
72
|
this.setBit(y * this.width + x);
|
|
78
73
|
},
|
|
79
|
-
|
|
80
74
|
/**
|
|
81
75
|
* Clear the bit of a pixel using coordinates.
|
|
82
76
|
* @memberof Image
|
|
@@ -87,7 +81,6 @@ const bitMethods = {
|
|
|
87
81
|
clearBitXY(x, y) {
|
|
88
82
|
this.clearBit(y * this.width + x);
|
|
89
83
|
},
|
|
90
|
-
|
|
91
84
|
/**
|
|
92
85
|
* Toggle (invert) the bit of a pixel using coordinates.
|
|
93
86
|
* @memberof Image
|
|
@@ -98,17 +91,13 @@ const bitMethods = {
|
|
|
98
91
|
toggleBitXY(x, y) {
|
|
99
92
|
this.toggleBit(y * this.width + x);
|
|
100
93
|
}
|
|
101
|
-
|
|
102
94
|
};
|
|
103
|
-
|
|
104
95
|
function getSlot(pixel) {
|
|
105
96
|
return pixel >> 3;
|
|
106
97
|
}
|
|
107
|
-
|
|
108
98
|
function getShift(pixel) {
|
|
109
99
|
return 7 - (pixel & 0b00000111);
|
|
110
100
|
}
|
|
111
|
-
|
|
112
101
|
function setBitMethods(Image) {
|
|
113
102
|
for (const i in bitMethods) {
|
|
114
103
|
Image.prototype[i] = bitMethods[i];
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = checkProcessable;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* This method checks if a process can be applied on the current image
|
|
10
9
|
* @memberof Image
|
|
@@ -20,49 +19,39 @@ function checkProcessable(processName, options = {}) {
|
|
|
20
19
|
components,
|
|
21
20
|
channels
|
|
22
21
|
} = options;
|
|
23
|
-
|
|
24
22
|
if (typeof processName !== 'string' || processName.length === 0) {
|
|
25
23
|
throw new TypeError('processName must be a string');
|
|
26
24
|
}
|
|
27
|
-
|
|
28
25
|
if (bitDepth) {
|
|
29
26
|
if (!Array.isArray(bitDepth)) {
|
|
30
27
|
bitDepth = [bitDepth];
|
|
31
28
|
}
|
|
32
|
-
|
|
33
29
|
if (!bitDepth.includes(this.bitDepth)) {
|
|
34
30
|
throw new TypeError(`The process: ${processName} can only be applied if bit depth is in: ${bitDepth}`);
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
|
-
|
|
38
33
|
if (alpha) {
|
|
39
34
|
if (!Array.isArray(alpha)) {
|
|
40
35
|
alpha = [alpha];
|
|
41
36
|
}
|
|
42
|
-
|
|
43
37
|
if (!alpha.includes(this.alpha)) {
|
|
44
38
|
throw new TypeError(`The process: ${processName} can only be applied if alpha is in: ${alpha}`);
|
|
45
39
|
}
|
|
46
40
|
}
|
|
47
|
-
|
|
48
41
|
if (colorModel) {
|
|
49
42
|
if (!Array.isArray(colorModel)) {
|
|
50
43
|
colorModel = [colorModel];
|
|
51
44
|
}
|
|
52
|
-
|
|
53
45
|
if (!colorModel.includes(this.colorModel)) {
|
|
54
46
|
throw new TypeError(`The process: ${processName} can only be applied if color model is in: ${colorModel}`);
|
|
55
47
|
}
|
|
56
48
|
}
|
|
57
|
-
|
|
58
49
|
if (components) {
|
|
59
50
|
if (!Array.isArray(components)) {
|
|
60
51
|
components = [components];
|
|
61
52
|
}
|
|
62
|
-
|
|
63
53
|
if (!components.includes(this.components)) {
|
|
64
54
|
let errorMessage = `The process: ${processName} can only be applied if the number of components is in: ${components}`;
|
|
65
|
-
|
|
66
55
|
if (components.length === 1 && components[0] === 1) {
|
|
67
56
|
throw new TypeError(`${errorMessage}.\rYou should transform your image using "image.grey()" before applying the algorithm.`);
|
|
68
57
|
} else {
|
|
@@ -70,12 +59,10 @@ function checkProcessable(processName, options = {}) {
|
|
|
70
59
|
}
|
|
71
60
|
}
|
|
72
61
|
}
|
|
73
|
-
|
|
74
62
|
if (channels) {
|
|
75
63
|
if (!Array.isArray(channels)) {
|
|
76
64
|
channels = [channels];
|
|
77
65
|
}
|
|
78
|
-
|
|
79
66
|
if (!channels.includes(this.channels)) {
|
|
80
67
|
throw new TypeError(`The process: ${processName} can only be applied if the number of channels is in: ${channels}`);
|
|
81
68
|
}
|