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 = dilate;
|
|
7
|
-
|
|
8
7
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* Dilatation is one of two fundamental operations (with erosion) in morphological
|
|
14
11
|
* image processing from which all other morphological operations are based (from Wikipedia).
|
|
@@ -32,13 +29,10 @@ function dilate(options = {}) {
|
|
|
32
29
|
components: 1,
|
|
33
30
|
alpha: 0
|
|
34
31
|
});
|
|
35
|
-
|
|
36
32
|
if (kernel.columns % 2 === 0 || kernel.rows % 2 === 0) {
|
|
37
33
|
throw new TypeError('dilate: The number of rows and columns of the kernel must be odd');
|
|
38
34
|
}
|
|
39
|
-
|
|
40
35
|
let onlyOnes = true;
|
|
41
|
-
|
|
42
36
|
outer: for (const row of kernel) {
|
|
43
37
|
for (const value of row) {
|
|
44
38
|
if (value !== 1) {
|
|
@@ -47,9 +41,7 @@ function dilate(options = {}) {
|
|
|
47
41
|
}
|
|
48
42
|
}
|
|
49
43
|
}
|
|
50
|
-
|
|
51
44
|
let result = this;
|
|
52
|
-
|
|
53
45
|
for (let i = 0; i < iterations; i++) {
|
|
54
46
|
if (this.bitDepth === 1) {
|
|
55
47
|
if (onlyOnes) {
|
|
@@ -57,33 +49,26 @@ function dilate(options = {}) {
|
|
|
57
49
|
result = dilateOnceBinaryOnlyOnes(result, newImage, kernel.length, kernel[0].length);
|
|
58
50
|
} else {
|
|
59
51
|
const newImage = _Image.default.createFrom(result);
|
|
60
|
-
|
|
61
52
|
result = dilateOnceBinary(result, newImage, kernel);
|
|
62
53
|
}
|
|
63
54
|
} else if (onlyOnes) {
|
|
64
55
|
const newImage = _Image.default.createFrom(result);
|
|
65
|
-
|
|
66
56
|
result = dilateOnceGreyOnlyOnes(result, newImage, kernel.length, kernel[0].length);
|
|
67
57
|
} else {
|
|
68
58
|
const newImage = _Image.default.createFrom(result);
|
|
69
|
-
|
|
70
59
|
result = dilateOnceGrey(result, newImage, kernel);
|
|
71
60
|
}
|
|
72
61
|
}
|
|
73
|
-
|
|
74
62
|
return result;
|
|
75
63
|
}
|
|
76
|
-
|
|
77
64
|
function dilateOnceGrey(img, newImage, kernel) {
|
|
78
65
|
const kernelWidth = kernel.length;
|
|
79
66
|
const kernelHeight = kernel[0].length;
|
|
80
67
|
let radiusX = (kernelWidth - 1) / 2;
|
|
81
68
|
let radiusY = (kernelHeight - 1) / 2;
|
|
82
|
-
|
|
83
69
|
for (let y = 0; y < img.height; y++) {
|
|
84
70
|
for (let x = 0; x < img.width; x++) {
|
|
85
71
|
let max = 0;
|
|
86
|
-
|
|
87
72
|
for (let jj = 0; jj < kernelHeight; jj++) {
|
|
88
73
|
for (let ii = 0; ii < kernelWidth; ii++) {
|
|
89
74
|
if (kernel[ii][jj] !== 1) continue;
|
|
@@ -94,64 +79,49 @@ function dilateOnceGrey(img, newImage, kernel) {
|
|
|
94
79
|
if (value > max) max = value;
|
|
95
80
|
}
|
|
96
81
|
}
|
|
97
|
-
|
|
98
82
|
newImage.setValueXY(x, y, 0, max);
|
|
99
83
|
}
|
|
100
84
|
}
|
|
101
|
-
|
|
102
85
|
return newImage;
|
|
103
86
|
}
|
|
104
|
-
|
|
105
87
|
function dilateOnceGreyOnlyOnes(img, newImage, kernelWidth, kernelHeight) {
|
|
106
88
|
const radiusX = (kernelWidth - 1) / 2;
|
|
107
89
|
const radiusY = (kernelHeight - 1) / 2;
|
|
108
90
|
const maxList = [];
|
|
109
|
-
|
|
110
91
|
for (let x = 0; x < img.width; x++) {
|
|
111
92
|
maxList.push(0);
|
|
112
93
|
}
|
|
113
|
-
|
|
114
94
|
for (let y = 0; y < img.height; y++) {
|
|
115
95
|
for (let x = 0; x < img.width; x++) {
|
|
116
96
|
let max = 0;
|
|
117
|
-
|
|
118
97
|
for (let h = Math.max(0, y - radiusY); h < Math.min(img.height, y + radiusY + 1); h++) {
|
|
119
98
|
const value = img.getValueXY(x, h, 0);
|
|
120
|
-
|
|
121
99
|
if (value > max) {
|
|
122
100
|
max = value;
|
|
123
101
|
}
|
|
124
102
|
}
|
|
125
|
-
|
|
126
103
|
maxList[x] = max;
|
|
127
104
|
}
|
|
128
|
-
|
|
129
105
|
for (let x = 0; x < img.width; x++) {
|
|
130
106
|
let max = 0;
|
|
131
|
-
|
|
132
107
|
for (let i = Math.max(0, x - radiusX); i < Math.min(img.width, x + radiusX + 1); i++) {
|
|
133
108
|
if (maxList[i] > max) {
|
|
134
109
|
max = maxList[i];
|
|
135
110
|
}
|
|
136
111
|
}
|
|
137
|
-
|
|
138
112
|
newImage.setValueXY(x, y, 0, max);
|
|
139
113
|
}
|
|
140
114
|
}
|
|
141
|
-
|
|
142
115
|
return newImage;
|
|
143
116
|
}
|
|
144
|
-
|
|
145
117
|
function dilateOnceBinary(img, newImage, kernel) {
|
|
146
118
|
const kernelWidth = kernel.length;
|
|
147
119
|
const kernelHeight = kernel[0].length;
|
|
148
120
|
let radiusX = (kernelWidth - 1) / 2;
|
|
149
121
|
let radiusY = (kernelHeight - 1) / 2;
|
|
150
|
-
|
|
151
122
|
for (let y = 0; y < img.height; y++) {
|
|
152
123
|
for (let x = 0; x < img.width; x++) {
|
|
153
124
|
let max = 0;
|
|
154
|
-
|
|
155
125
|
intLoop: for (let jj = 0; jj < kernelHeight; jj++) {
|
|
156
126
|
for (let ii = 0; ii < kernelWidth; ii++) {
|
|
157
127
|
if (kernel[ii][jj] !== 1) continue;
|
|
@@ -159,36 +129,29 @@ function dilateOnceBinary(img, newImage, kernel) {
|
|
|
159
129
|
let j = jj - radiusY + y;
|
|
160
130
|
if (j < 0 || i < 0 || i >= img.width || j >= img.height) continue;
|
|
161
131
|
const value = img.getBitXY(i, j);
|
|
162
|
-
|
|
163
132
|
if (value === 1) {
|
|
164
133
|
max = 1;
|
|
165
134
|
break intLoop;
|
|
166
135
|
}
|
|
167
136
|
}
|
|
168
137
|
}
|
|
169
|
-
|
|
170
138
|
if (max === 1) {
|
|
171
139
|
newImage.setBitXY(x, y);
|
|
172
140
|
}
|
|
173
141
|
}
|
|
174
142
|
}
|
|
175
|
-
|
|
176
143
|
return newImage;
|
|
177
144
|
}
|
|
178
|
-
|
|
179
145
|
function dilateOnceBinaryOnlyOnes(img, newImage, kernelWidth, kernelHeight) {
|
|
180
146
|
const radiusX = (kernelWidth - 1) / 2;
|
|
181
147
|
const radiusY = (kernelHeight - 1) / 2;
|
|
182
148
|
const maxList = [];
|
|
183
|
-
|
|
184
149
|
for (let x = 0; x < img.width; x++) {
|
|
185
150
|
maxList.push(1);
|
|
186
151
|
}
|
|
187
|
-
|
|
188
152
|
for (let y = 0; y < img.height; y++) {
|
|
189
153
|
for (let x = 0; x < img.width; x++) {
|
|
190
154
|
maxList[x] = 0;
|
|
191
|
-
|
|
192
155
|
for (let h = Math.max(0, y - radiusY); h < Math.min(img.height, y + radiusY + 1); h++) {
|
|
193
156
|
if (img.getBitXY(x, h) === 1) {
|
|
194
157
|
maxList[x] = 1;
|
|
@@ -196,10 +159,8 @@ function dilateOnceBinaryOnlyOnes(img, newImage, kernelWidth, kernelHeight) {
|
|
|
196
159
|
}
|
|
197
160
|
}
|
|
198
161
|
}
|
|
199
|
-
|
|
200
162
|
for (let x = 0; x < img.width; x++) {
|
|
201
163
|
if (newImage.getBitXY(x, y) === 1) continue;
|
|
202
|
-
|
|
203
164
|
for (let i = Math.max(0, x - radiusX); i < Math.min(img.width, x + radiusX + 1); i++) {
|
|
204
165
|
if (maxList[i] === 1) {
|
|
205
166
|
newImage.setBitXY(x, y);
|
|
@@ -208,6 +169,5 @@ function dilateOnceBinaryOnlyOnes(img, newImage, kernelWidth, kernelHeight) {
|
|
|
208
169
|
}
|
|
209
170
|
}
|
|
210
171
|
}
|
|
211
|
-
|
|
212
172
|
return newImage;
|
|
213
173
|
}
|
|
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = erode;
|
|
7
|
-
|
|
8
7
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* Erosion is one of two fundamental operations (with dilatation) in morphological
|
|
14
11
|
* image processing from which all other morphological operations are based (from Wikipedia).
|
|
@@ -32,13 +29,10 @@ function erode(options = {}) {
|
|
|
32
29
|
components: 1,
|
|
33
30
|
alpha: 0
|
|
34
31
|
});
|
|
35
|
-
|
|
36
32
|
if (kernel.columns % 2 === 0 || kernel.rows % 2 === 0) {
|
|
37
33
|
throw new TypeError('erode: The number of rows and columns of the kernel must be odd');
|
|
38
34
|
}
|
|
39
|
-
|
|
40
35
|
let onlyOnes = true;
|
|
41
|
-
|
|
42
36
|
outer: for (const row of kernel) {
|
|
43
37
|
for (const value of row) {
|
|
44
38
|
if (value !== 1) {
|
|
@@ -47,9 +41,7 @@ function erode(options = {}) {
|
|
|
47
41
|
}
|
|
48
42
|
}
|
|
49
43
|
}
|
|
50
|
-
|
|
51
44
|
let result = this;
|
|
52
|
-
|
|
53
45
|
for (let i = 0; i < iterations; i++) {
|
|
54
46
|
if (this.bitDepth === 1) {
|
|
55
47
|
if (onlyOnes) {
|
|
@@ -57,33 +49,26 @@ function erode(options = {}) {
|
|
|
57
49
|
result = erodeOnceBinaryOnlyOnes(result, newImage, kernel.length, kernel[0].length);
|
|
58
50
|
} else {
|
|
59
51
|
const newImage = _Image.default.createFrom(result);
|
|
60
|
-
|
|
61
52
|
result = erodeOnceBinary(result, newImage, kernel);
|
|
62
53
|
}
|
|
63
54
|
} else if (onlyOnes) {
|
|
64
55
|
const newImage = _Image.default.createFrom(result);
|
|
65
|
-
|
|
66
56
|
result = erodeOnceGreyOnlyOnes(result, newImage, kernel.length, kernel[0].length);
|
|
67
57
|
} else {
|
|
68
58
|
const newImage = _Image.default.createFrom(result);
|
|
69
|
-
|
|
70
59
|
result = erodeOnceGrey(result, newImage, kernel);
|
|
71
60
|
}
|
|
72
61
|
}
|
|
73
|
-
|
|
74
62
|
return result;
|
|
75
63
|
}
|
|
76
|
-
|
|
77
64
|
function erodeOnceGrey(img, newImage, kernel) {
|
|
78
65
|
const kernelWidth = kernel.length;
|
|
79
66
|
const kernelHeight = kernel[0].length;
|
|
80
67
|
let radiusX = (kernelWidth - 1) / 2;
|
|
81
68
|
let radiusY = (kernelHeight - 1) / 2;
|
|
82
|
-
|
|
83
69
|
for (let y = 0; y < img.height; y++) {
|
|
84
70
|
for (let x = 0; x < img.width; x++) {
|
|
85
71
|
let min = img.maxValue;
|
|
86
|
-
|
|
87
72
|
for (let jj = 0; jj < kernelHeight; jj++) {
|
|
88
73
|
for (let ii = 0; ii < kernelWidth; ii++) {
|
|
89
74
|
if (kernel[ii][jj] !== 1) continue;
|
|
@@ -94,64 +79,49 @@ function erodeOnceGrey(img, newImage, kernel) {
|
|
|
94
79
|
if (value < min) min = value;
|
|
95
80
|
}
|
|
96
81
|
}
|
|
97
|
-
|
|
98
82
|
newImage.setValueXY(x, y, 0, min);
|
|
99
83
|
}
|
|
100
84
|
}
|
|
101
|
-
|
|
102
85
|
return newImage;
|
|
103
86
|
}
|
|
104
|
-
|
|
105
87
|
function erodeOnceGreyOnlyOnes(img, newImage, kernelWidth, kernelHeight) {
|
|
106
88
|
const radiusX = (kernelWidth - 1) / 2;
|
|
107
89
|
const radiusY = (kernelHeight - 1) / 2;
|
|
108
90
|
const minList = [];
|
|
109
|
-
|
|
110
91
|
for (let x = 0; x < img.width; x++) {
|
|
111
92
|
minList.push(0);
|
|
112
93
|
}
|
|
113
|
-
|
|
114
94
|
for (let y = 0; y < img.height; y++) {
|
|
115
95
|
for (let x = 0; x < img.width; x++) {
|
|
116
96
|
let min = img.maxValue;
|
|
117
|
-
|
|
118
97
|
for (let h = Math.max(0, y - radiusY); h < Math.min(img.height, y + radiusY + 1); h++) {
|
|
119
98
|
const value = img.getValueXY(x, h, 0);
|
|
120
|
-
|
|
121
99
|
if (value < min) {
|
|
122
100
|
min = value;
|
|
123
101
|
}
|
|
124
102
|
}
|
|
125
|
-
|
|
126
103
|
minList[x] = min;
|
|
127
104
|
}
|
|
128
|
-
|
|
129
105
|
for (let x = 0; x < img.width; x++) {
|
|
130
106
|
let min = img.maxValue;
|
|
131
|
-
|
|
132
107
|
for (let i = Math.max(0, x - radiusX); i < Math.min(img.width, x + radiusX + 1); i++) {
|
|
133
108
|
if (minList[i] < min) {
|
|
134
109
|
min = minList[i];
|
|
135
110
|
}
|
|
136
111
|
}
|
|
137
|
-
|
|
138
112
|
newImage.setValueXY(x, y, 0, min);
|
|
139
113
|
}
|
|
140
114
|
}
|
|
141
|
-
|
|
142
115
|
return newImage;
|
|
143
116
|
}
|
|
144
|
-
|
|
145
117
|
function erodeOnceBinary(img, newImage, kernel) {
|
|
146
118
|
const kernelWidth = kernel.length;
|
|
147
119
|
const kernelHeight = kernel[0].length;
|
|
148
120
|
let radiusX = (kernelWidth - 1) / 2;
|
|
149
121
|
let radiusY = (kernelHeight - 1) / 2;
|
|
150
|
-
|
|
151
122
|
for (let y = 0; y < img.height; y++) {
|
|
152
123
|
for (let x = 0; x < img.width; x++) {
|
|
153
124
|
let min = 1;
|
|
154
|
-
|
|
155
125
|
intLoop: for (let jj = 0; jj < kernelHeight; jj++) {
|
|
156
126
|
for (let ii = 0; ii < kernelWidth; ii++) {
|
|
157
127
|
if (kernel[ii][jj] !== 1) continue;
|
|
@@ -159,36 +129,29 @@ function erodeOnceBinary(img, newImage, kernel) {
|
|
|
159
129
|
let j = jj - radiusY + y;
|
|
160
130
|
if (j < 0 || i < 0 || i >= img.width || j >= img.height) continue;
|
|
161
131
|
const value = img.getBitXY(i, j);
|
|
162
|
-
|
|
163
132
|
if (value === 0) {
|
|
164
133
|
min = 0;
|
|
165
134
|
break intLoop;
|
|
166
135
|
}
|
|
167
136
|
}
|
|
168
137
|
}
|
|
169
|
-
|
|
170
138
|
if (min === 1) {
|
|
171
139
|
newImage.setBitXY(x, y);
|
|
172
140
|
}
|
|
173
141
|
}
|
|
174
142
|
}
|
|
175
|
-
|
|
176
143
|
return newImage;
|
|
177
144
|
}
|
|
178
|
-
|
|
179
145
|
function erodeOnceBinaryOnlyOnes(img, newImage, kernelWidth, kernelHeight) {
|
|
180
146
|
const radiusX = (kernelWidth - 1) / 2;
|
|
181
147
|
const radiusY = (kernelHeight - 1) / 2;
|
|
182
148
|
const minList = [];
|
|
183
|
-
|
|
184
149
|
for (let x = 0; x < img.width; x++) {
|
|
185
150
|
minList.push(0);
|
|
186
151
|
}
|
|
187
|
-
|
|
188
152
|
for (let y = 0; y < img.height; y++) {
|
|
189
153
|
for (let x = 0; x < img.width; x++) {
|
|
190
154
|
minList[x] = 1;
|
|
191
|
-
|
|
192
155
|
for (let h = Math.max(0, y - radiusY); h < Math.min(img.height, y + radiusY + 1); h++) {
|
|
193
156
|
if (img.getBitXY(x, h) === 0) {
|
|
194
157
|
minList[x] = 0;
|
|
@@ -196,10 +159,8 @@ function erodeOnceBinaryOnlyOnes(img, newImage, kernelWidth, kernelHeight) {
|
|
|
196
159
|
}
|
|
197
160
|
}
|
|
198
161
|
}
|
|
199
|
-
|
|
200
162
|
for (let x = 0; x < img.width; x++) {
|
|
201
163
|
if (newImage.getBitXY(x, y) === 0) continue;
|
|
202
|
-
|
|
203
164
|
for (let i = Math.max(0, x - radiusX); i < Math.min(img.width, x + radiusX + 1); i++) {
|
|
204
165
|
if (minList[i] === 0) {
|
|
205
166
|
newImage.clearBitXY(x, y);
|
|
@@ -208,6 +169,5 @@ function erodeOnceBinaryOnlyOnes(img, newImage, kernelWidth, kernelHeight) {
|
|
|
208
169
|
}
|
|
209
170
|
}
|
|
210
171
|
}
|
|
211
|
-
|
|
212
172
|
return newImage;
|
|
213
173
|
}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = morphologicalGradient;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* In mathematical morphology and digital image processing, a morphological gradient is the difference between the dilation and the erosion of a given image. It is an image where each pixel value (typically non-negative) indicates the contrast intensity in the close neighborhood of that pixel. It is useful for edge detection and segmentation applications.
|
|
10
9
|
* http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html
|
|
@@ -25,13 +24,10 @@ function morphologicalGradient(options = {}) {
|
|
|
25
24
|
components: 1,
|
|
26
25
|
alpha: 0
|
|
27
26
|
});
|
|
28
|
-
|
|
29
27
|
if (kernel.columns % 2 === 0 || kernel.rows % 2 === 0) {
|
|
30
28
|
throw new TypeError('morphologicalGradient: The number of rows and columns of the kernel must be odd');
|
|
31
29
|
}
|
|
32
|
-
|
|
33
30
|
let newImage = this;
|
|
34
|
-
|
|
35
31
|
for (let i = 0; i < iterations; i++) {
|
|
36
32
|
let dilatedImage = newImage.dilate({
|
|
37
33
|
kernel
|
|
@@ -43,6 +39,5 @@ function morphologicalGradient(options = {}) {
|
|
|
43
39
|
absolute: true
|
|
44
40
|
});
|
|
45
41
|
}
|
|
46
|
-
|
|
47
42
|
return newImage;
|
|
48
43
|
}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = open;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* In mathematical morphology, opening is the dilation of the erosion of a set A by a structuring element B.
|
|
10
9
|
* Together with closing, the opening serves in computer vision and image processing as a basic workhorse of morphological noise removal.
|
|
@@ -28,13 +27,10 @@ function open(options = {}) {
|
|
|
28
27
|
components: 1,
|
|
29
28
|
alpha: 0
|
|
30
29
|
});
|
|
31
|
-
|
|
32
30
|
if (kernel.columns % 2 === 0 || kernel.rows % 2 === 0) {
|
|
33
31
|
throw new TypeError('open: The number of rows and columns of the kernel must be odd');
|
|
34
32
|
}
|
|
35
|
-
|
|
36
33
|
let newImage = this;
|
|
37
|
-
|
|
38
34
|
for (let i = 0; i < iterations; i++) {
|
|
39
35
|
newImage = newImage.erode({
|
|
40
36
|
kernel
|
|
@@ -43,6 +39,5 @@ function open(options = {}) {
|
|
|
43
39
|
kernel
|
|
44
40
|
});
|
|
45
41
|
}
|
|
46
|
-
|
|
47
42
|
return newImage;
|
|
48
43
|
}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = topHat;
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* This function is the white top hat (also called top hat). In mathematical morphology and digital image processing,
|
|
10
9
|
* top-hat transform is an operation that extracts small elements and details from given images.
|
|
@@ -28,13 +27,10 @@ function topHat(options = {}) {
|
|
|
28
27
|
components: 1,
|
|
29
28
|
alpha: 0
|
|
30
29
|
});
|
|
31
|
-
|
|
32
30
|
if (kernel.length % 2 === 0 || kernel[0].length % 2 === 0) {
|
|
33
31
|
throw new TypeError('topHat: The number of rows and columns of the kernel must be odd');
|
|
34
32
|
}
|
|
35
|
-
|
|
36
33
|
let newImage = this;
|
|
37
|
-
|
|
38
34
|
for (let i = 0; i < iterations; i++) {
|
|
39
35
|
let openImage = newImage.open({
|
|
40
36
|
kernel
|
|
@@ -43,6 +39,5 @@ function topHat(options = {}) {
|
|
|
43
39
|
absolute: true
|
|
44
40
|
});
|
|
45
41
|
}
|
|
46
|
-
|
|
47
42
|
return newImage;
|
|
48
43
|
}
|
|
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = cannyEdge;
|
|
7
|
-
|
|
8
7
|
var _cannyEdgeDetector = _interopRequireDefault(require("canny-edge-detector"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* @memberof Image
|
|
14
11
|
* @instance
|
|
@@ -4,23 +4,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = convolution;
|
|
7
|
-
|
|
8
7
|
var _mlMatrixConvolution = require("ml-matrix-convolution");
|
|
9
|
-
|
|
10
8
|
var _channel = require("../../util/channel");
|
|
11
|
-
|
|
12
9
|
var _kernel = require("../../util/kernel");
|
|
13
|
-
|
|
14
10
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
15
|
-
|
|
16
11
|
var _clamp = require("../internal/clamp");
|
|
17
|
-
|
|
18
12
|
var _convolutionSeparable = _interopRequireDefault(require("./convolutionSeparable"));
|
|
19
|
-
|
|
20
13
|
var _getSeparatedKernel = _interopRequireDefault(require("./getSeparatedKernel"));
|
|
21
|
-
|
|
22
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
-
|
|
24
15
|
/**
|
|
25
16
|
* @memberof Image
|
|
26
17
|
* @instance
|
|
@@ -47,11 +38,8 @@ function convolution(kernel, options = {}) {
|
|
|
47
38
|
} = options;
|
|
48
39
|
let createOptions = {};
|
|
49
40
|
if (bitDepth) createOptions.bitDepth = bitDepth;
|
|
50
|
-
|
|
51
41
|
let newImage = _Image.default.createFrom(this, createOptions);
|
|
52
|
-
|
|
53
42
|
channels = (0, _channel.validateArrayOfChannels)(this, channels, true);
|
|
54
|
-
|
|
55
43
|
if (algorithm !== 'separable') {
|
|
56
44
|
({
|
|
57
45
|
kernel
|
|
@@ -59,10 +47,8 @@ function convolution(kernel, options = {}) {
|
|
|
59
47
|
} else if (!Array.isArray(kernel) || kernel.length !== 2) {
|
|
60
48
|
throw new RangeError('separable convolution requires two arrays of numbers to represent the kernel');
|
|
61
49
|
}
|
|
62
|
-
|
|
63
50
|
if (algorithm === 'auto') {
|
|
64
51
|
let separatedKernel = (0, _getSeparatedKernel.default)(kernel);
|
|
65
|
-
|
|
66
52
|
if (separatedKernel !== null) {
|
|
67
53
|
algorithm = 'separable';
|
|
68
54
|
kernel = separatedKernel;
|
|
@@ -72,9 +58,7 @@ function convolution(kernel, options = {}) {
|
|
|
72
58
|
algorithm = 'direct';
|
|
73
59
|
}
|
|
74
60
|
}
|
|
75
|
-
|
|
76
61
|
let halfHeight, halfWidth;
|
|
77
|
-
|
|
78
62
|
if (algorithm === 'separable') {
|
|
79
63
|
halfHeight = Math.floor(kernel[0].length / 2);
|
|
80
64
|
halfWidth = Math.floor(kernel[1].length / 2);
|
|
@@ -82,21 +66,18 @@ function convolution(kernel, options = {}) {
|
|
|
82
66
|
halfHeight = Math.floor(kernel.length / 2);
|
|
83
67
|
halfWidth = Math.floor(kernel[0].length / 2);
|
|
84
68
|
}
|
|
85
|
-
|
|
86
69
|
let clamped = newImage.isClamped;
|
|
87
70
|
let tmpData = new Array(this.height * this.width);
|
|
88
71
|
let index, x, y, channel, c, tmpResult;
|
|
89
|
-
|
|
90
72
|
for (channel = 0; channel < channels.length; channel++) {
|
|
91
|
-
c = channels[channel];
|
|
92
|
-
|
|
73
|
+
c = channels[channel];
|
|
74
|
+
// Copy the channel in a single array
|
|
93
75
|
for (y = 0; y < this.height; y++) {
|
|
94
76
|
for (x = 0; x < this.width; x++) {
|
|
95
77
|
index = y * this.width + x;
|
|
96
78
|
tmpData[index] = this.data[index * this.channels + c];
|
|
97
79
|
}
|
|
98
80
|
}
|
|
99
|
-
|
|
100
81
|
if (algorithm === 'direct') {
|
|
101
82
|
tmpResult = (0, _mlMatrixConvolution.direct)(tmpData, kernel, {
|
|
102
83
|
rows: this.height,
|
|
@@ -106,17 +87,14 @@ function convolution(kernel, options = {}) {
|
|
|
106
87
|
});
|
|
107
88
|
} else if (algorithm === 'separable') {
|
|
108
89
|
tmpResult = (0, _convolutionSeparable.default)(tmpData, kernel, this.width, this.height);
|
|
109
|
-
|
|
110
90
|
if (normalize) {
|
|
111
91
|
divisor = 0;
|
|
112
|
-
|
|
113
92
|
for (let i = 0; i < kernel[0].length; i++) {
|
|
114
93
|
for (let j = 0; j < kernel[1].length; j++) {
|
|
115
94
|
divisor += kernel[0][i] * kernel[1][j];
|
|
116
95
|
}
|
|
117
96
|
}
|
|
118
97
|
}
|
|
119
|
-
|
|
120
98
|
if (divisor !== 1) {
|
|
121
99
|
for (let i = 0; i < tmpResult.length; i++) {
|
|
122
100
|
tmpResult[i] /= divisor;
|
|
@@ -129,13 +107,12 @@ function convolution(kernel, options = {}) {
|
|
|
129
107
|
normalize: normalize,
|
|
130
108
|
divisor: divisor
|
|
131
109
|
});
|
|
132
|
-
}
|
|
133
|
-
|
|
110
|
+
}
|
|
134
111
|
|
|
112
|
+
// Copy the result to the output image
|
|
135
113
|
for (y = 0; y < this.height; y++) {
|
|
136
114
|
for (x = 0; x < this.width; x++) {
|
|
137
115
|
index = y * this.width + x;
|
|
138
|
-
|
|
139
116
|
if (clamped) {
|
|
140
117
|
newImage.data[index * this.channels + c] = (0, _clamp.clamp)(tmpResult[index], newImage);
|
|
141
118
|
} else {
|
|
@@ -143,27 +120,25 @@ function convolution(kernel, options = {}) {
|
|
|
143
120
|
}
|
|
144
121
|
}
|
|
145
122
|
}
|
|
146
|
-
}
|
|
123
|
+
}
|
|
124
|
+
// if the kernel was not applied on the alpha channel we just copy it
|
|
147
125
|
// TODO: in general we should copy the channels that where not changed
|
|
148
126
|
// TODO: probably we should just copy the image at the beginning ?
|
|
149
|
-
|
|
150
|
-
|
|
151
127
|
if (this.alpha && !channels.includes(this.channels)) {
|
|
152
128
|
for (x = this.components; x < this.data.length; x = x + this.channels) {
|
|
153
129
|
newImage.data[x] = this.data[x];
|
|
154
130
|
}
|
|
155
|
-
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// I only can have 3 types of borders:
|
|
156
134
|
// 1. Considering the image as periodic: periodic
|
|
157
135
|
// 2. Extend the interior borders: copy
|
|
158
136
|
// 3. fill with a color: set
|
|
159
|
-
|
|
160
|
-
|
|
161
137
|
if (border !== 'periodic') {
|
|
162
138
|
newImage.setBorder({
|
|
163
139
|
size: [halfWidth, halfHeight],
|
|
164
140
|
algorithm: border
|
|
165
141
|
});
|
|
166
142
|
}
|
|
167
|
-
|
|
168
143
|
return newImage;
|
|
169
144
|
}
|
|
@@ -4,9 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = convolutionSeparable;
|
|
7
|
-
|
|
8
7
|
var _mlConvolution = require("ml-convolution");
|
|
9
|
-
|
|
10
8
|
function convolutionSeparable(data, separatedKernel, width, height) {
|
|
11
9
|
const result = new Array(data.length);
|
|
12
10
|
let tmp, conv, offset, kernel;
|
|
@@ -14,35 +12,27 @@ function convolutionSeparable(data, separatedKernel, width, height) {
|
|
|
14
12
|
offset = (kernel.length - 1) / 2;
|
|
15
13
|
conv = new Array(width + kernel.length - 1);
|
|
16
14
|
tmp = new Array(width);
|
|
17
|
-
|
|
18
15
|
for (let y = 0; y < height; y++) {
|
|
19
16
|
for (let x = 0; x < width; x++) {
|
|
20
17
|
tmp[x] = data[y * width + x];
|
|
21
18
|
}
|
|
22
|
-
|
|
23
19
|
(0, _mlConvolution.directConvolution)(tmp, kernel, conv);
|
|
24
|
-
|
|
25
20
|
for (let x = 0; x < width; x++) {
|
|
26
21
|
result[y * width + x] = conv[offset + x];
|
|
27
22
|
}
|
|
28
23
|
}
|
|
29
|
-
|
|
30
24
|
kernel = separatedKernel[0];
|
|
31
25
|
offset = (kernel.length - 1) / 2;
|
|
32
26
|
conv = new Array(height + kernel.length - 1);
|
|
33
27
|
tmp = new Array(height);
|
|
34
|
-
|
|
35
28
|
for (let x = 0; x < width; x++) {
|
|
36
29
|
for (let y = 0; y < height; y++) {
|
|
37
30
|
tmp[y] = result[y * width + x];
|
|
38
31
|
}
|
|
39
|
-
|
|
40
32
|
(0, _mlConvolution.directConvolution)(tmp, kernel, conv);
|
|
41
|
-
|
|
42
33
|
for (let y = 0; y < height; y++) {
|
|
43
34
|
result[y * width + x] = conv[offset + y];
|
|
44
35
|
}
|
|
45
36
|
}
|
|
46
|
-
|
|
47
37
|
return result;
|
|
48
38
|
}
|