-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHW8.js
374 lines (323 loc) · 14.9 KB
/
HW8.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
'use strict'
const cv = require('opencv')
const fs = require('fs')
const utils = require('./utils')
const BLACK = 0
const WHITE = 255
function Kernel (kernel, origin) {
this.kernel = kernel
this.origin = origin
this.points = []
for (let y = 0; y < kernel.length; y++) {
for (let x = 0; x < kernel[y].length; x++) {
if (kernel[y][x] >= 0) {
this.points.push({x: (x - origin.x), y: (y - origin.y)})
}
}
}
return this
}
function applyDilation (inputMat, kernel) {
let result = inputMat.copy()
for (let i = 0; i < inputMat.height(); i++) { // row
for (let j = 0; j < inputMat.width(); j++) { // column
let localMax = 0
for (let kernelIndex = 0; kernelIndex < kernel.points.length; kernelIndex++) {
let x = j + kernel.points[kernelIndex].x
let y = i + kernel.points[kernelIndex].y
if (x >= 0 && x <= inputMat.width() && y >= 0 && y <= inputMat.height()) {
localMax = Math.max(localMax, inputMat.pixelValueAt(y, x))
}
}
result.pixel(i, j, [localMax, localMax, localMax])
}
}
return result
}
function applyErosion (inputMat, kernel) {
let result = inputMat.copy()
for (let i = 0; i < inputMat.height(); i++) { // row
for (let j = 0; j < inputMat.width(); j++) { // column
let localMin = 255
for (let kernelIndex = 0; kernelIndex < kernel.points.length; kernelIndex++) {
let x = j + kernel.points[kernelIndex].x
let y = i + kernel.points[kernelIndex].y
if (x >= 0 && x <= inputMat.width() && y >= 0 && y <= inputMat.height()) {
localMin = Math.min(localMin, inputMat.pixelValueAt(y, x))
}
}
result.pixel(i, j, [localMin, localMin, localMin])
}
}
return result
}
function applyOpening (inputMat, kernel) {
return applyDilation(applyErosion(inputMat, kernel), kernel)
}
function applyClosing (inputMat, kernel) {
return applyErosion(applyDilation(inputMat, kernel), kernel)
}
function applyClosingThenOpening (inputMat, kernel) {
console.log('applyClosingThenOpening')
return applyOpening(applyClosing(inputMat, kernel), kernel)
}
function applyOpeningThenClosing (inputMat, kernel) {
console.log('applyOpeningThenClosing')
return applyClosing(applyOpening(inputMat, kernel), kernel)
}
function applyGaussianNoise (inputMat, amplitude) {
let gaussianMat = inputMat.copy()
for (let i = 0; i < inputMat.height(); i++) { // row
for (let j = 0; j < inputMat.width(); j++) { // column
let noiseValue = gaussianMat.pixelValueAt(i, j) + amplitude * randomGauss()
if (noiseValue > WHITE) {
noiseValue = WHITE
} else if (noiseValue < BLACK) {
noiseValue = BLACK
}
gaussianMat.pixel(i, j, [noiseValue, noiseValue, noiseValue])
}
}
return gaussianMat
}
function randomGauss () {
let a
let b = 0
for (a = 0; a < 12; a++) {
b += Math.random()
}
return b - 6
}
function applySaltAndPepper (inputMat, threshold) {
let saltPepperMat = inputMat.copy()
for (let i = 0; i < inputMat.height(); i++) { // row
for (let j = 0; j < inputMat.width(); j++) { // column
let random = Math.random()
if (random < threshold) {
saltPepperMat.pixel(i, j, [BLACK, BLACK, BLACK])
} else if (random > 1 - threshold) {
saltPepperMat.pixel(i, j, [WHITE, WHITE, WHITE])
}
}
}
return saltPepperMat
}
function applyBoxFilter (inputMat, boxWidth, boxHeight) {
let boxFilterMat = inputMat.copy()
let bounds = {
x: Math.floor(boxWidth / 2),
y: Math.floor(boxHeight / 2)
}
console.log('applying box filter', boxHeight, 'x', boxHeight)
for (let i = 0; i < inputMat.height(); i++) { // row
for (let j = 0; j < inputMat.width(); j++) { // column
let boxList = []
let localOrigin = {
x: j - bounds.x,
y: i - bounds.y
}
for (let m = 0; m < boxHeight; m++) { // row
for (let n = 0; n < boxWidth; n++) { // column
let result = {
x: localOrigin.x + n,
y: localOrigin.y + m
}
if (result.x >= 0 && result.x < boxFilterMat.width() && result.y >= 0 && result.y < boxFilterMat.height()) {
boxList.push(inputMat.pixelValueAt(result.y, result.x))
}
}
}
let value = boxList.reduce(function (a, b) {
return a + b
}) / boxList.length
boxFilterMat.pixel(i, j, [value, value, value])
}
}
return boxFilterMat
}
function median (values) {
values.sort(function (a, b) {
return a - b
})
var half = Math.floor(values.length / 2)
if (values.length % 2) {
return values[half]
} else {
return (values[half - 1] + values[half]) / 2.0
}
}
function applyMedianFilter (inputMat, boxWidth, boxHeight) {
let medianFilterMat = inputMat.copy()
let bounds = {
x: Math.floor(boxWidth / 2),
y: Math.floor(boxHeight / 2)
}
console.log('applying median filter', boxHeight, 'x', boxHeight)
for (let i = 0; i < inputMat.height(); i++) { // row
for (let j = 0; j < inputMat.width(); j++) { // column
let boxList = []
let localOrigin = {
x: j - bounds.x,
y: i - bounds.y
}
for (let m = 0; m < boxHeight; m++) { // row
for (let n = 0; n < boxWidth; n++) { // column
let result = {
x: localOrigin.x + n,
y: localOrigin.y + m
}
if (result.x >= 0 && result.x < inputMat.width() && result.y >= 0 && result.y < inputMat.height()) {
boxList.push(inputMat.pixelValueAt(result.y, result.x))
}
}
}
let medianValue = median(boxList)
medianFilterMat.pixel(i, j, [medianValue, medianValue, medianValue])
}
}
return medianFilterMat
}
function calculateSNR (originalMat, noiseMat) {
let originPixel = originalMat.copy()
let noisePixel = noiseMat.copy()
let size = originalMat.width() * originalMat.height()
let us = 0
let vs = 0
let un = 0
let vn = 0
for (let i = 0; i < originalMat.height(); i++) { // row
for (let j = 0; j < originalMat.width(); j++) { // column
us += originPixel.pixelValueAt(i, j)
}
}
us /= size
for (let i = 0; i < originalMat.height(); i++) { // row
for (let j = 0; j < originalMat.width(); j++) { // column
vs += Math.pow(originPixel.pixelValueAt(i, j) - us, 2)
}
}
vs /= size
for (let i = 0; i < originalMat.height(); i++) { // row
for (let j = 0; j < originalMat.width(); j++) { // column
un += noisePixel.pixelValueAt(i, j) - originPixel.pixelValueAt(i, j)
}
}
un /= size
for (let i = 0; i < originalMat.height(); i++) { // row
for (let j = 0; j < originalMat.width(); j++) { // column
vn += Math.pow(noisePixel.pixelValueAt(i, j) - originPixel.pixelValueAt(i, j) - un, 2)
}
}
vn /= size
let value = 20 * Math.log10(Math.sqrt(vs / vn))
console.log('SNR = ', value, 'us =', us, 'vs =', vs, 'un =', un, 'vn =', vn)
return value
}
function main () {
// read lena image from the file system using opencv
cv.readImage(process.argv[2], function (err, inputMat) {
if (err || inputMat.height() === 0 || inputMat.width === 0) {
console.log('input image error!')
return
}
let kernel = new Kernel([
[-1, 0, 0, 0, -1],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[-1, 0, 0, 0, -1]
], {x: 2, y: 2}) // origin is 2,2
let outputDirectory = './output/HW8/'
let stream = fs.createWriteStream(outputDirectory + 'SNR.txt')
let gaussian30Mat = applyGaussianNoise(inputMat, 30)
let gaussian10Mat = applyGaussianNoise(inputMat, 10)
let saltAndPepper005Mat = applySaltAndPepper(inputMat, 0.05)
let saltAndPepper01Mat = applySaltAndPepper(inputMat, 0.1)
gaussian30Mat.save(outputDirectory + 'HW8_gaussian_30.bmp')
gaussian10Mat.save(outputDirectory + 'HW8_gaussian_10.bmp')
saltAndPepper005Mat.save(outputDirectory + 'HW8_salt_and_pepper_005.bmp')
saltAndPepper01Mat.save(outputDirectory + 'HW8_salt_and_pepper_01.bmp')
stream.write('gaussian 10: ' + calculateSNR(inputMat, gaussian10Mat) + '\n')
stream.write('gaussian 30: ' + calculateSNR(inputMat, gaussian30Mat) + '\n')
stream.write('salt and pepper 0.05: ' + calculateSNR(inputMat, saltAndPepper005Mat) + '\n')
stream.write('salt and pepper 0.1: ' + calculateSNR(inputMat, saltAndPepper01Mat) + '\n')
// Box 3x3
let box33Gaussian10Mat = applyBoxFilter(gaussian10Mat, 3, 3)
let box33Gaussian30Mat = applyBoxFilter(gaussian30Mat, 3, 3)
let box33salt005Mat = applyBoxFilter(saltAndPepper005Mat, 3, 3)
let box33salt01Mat = applyBoxFilter(saltAndPepper01Mat, 3, 3)
box33Gaussian10Mat.save(outputDirectory + 'HW8_box_33_gaussian_10.bmp')
box33Gaussian30Mat.save(outputDirectory + 'HW8_box_33_gaussian_30.bmp')
box33salt005Mat.save(outputDirectory + 'HW8_box_33_salt_and_pepper_005.bmp')
box33salt01Mat.save(outputDirectory + 'HW8_box_33_salt_and_pepper_01.bmp')
stream.write('box 3x3 gaussian 10: ' + calculateSNR(inputMat, box33Gaussian10Mat) + '\n')
stream.write('box 3x3 gaussian 30: ' + calculateSNR(inputMat, box33Gaussian30Mat) + '\n')
stream.write('box 3x3 salt and pepper 0.05: ' + calculateSNR(inputMat, box33salt005Mat) + '\n')
stream.write('box 3x3 salt and pepper 0.1: ' + calculateSNR(inputMat, box33salt01Mat) + '\n')
// Box 5x5
let box55Gaussian10Mat = applyBoxFilter(gaussian10Mat, 5, 5)
let box55Gaussian30Mat = applyBoxFilter(gaussian30Mat, 5, 5)
let box55salt005Mat = applyBoxFilter(saltAndPepper005Mat, 5, 5)
let box55salt01Mat = applyBoxFilter(saltAndPepper01Mat, 5, 5)
box55Gaussian10Mat.save(outputDirectory + 'HW8_box_55_gaussian_10.bmp')
box55Gaussian30Mat.save(outputDirectory + 'HW8_box_55_gaussian_30.bmp')
box55salt005Mat.save(outputDirectory + 'HW8_box_55_salt_and_pepper_005.bmp')
box55salt01Mat.save(outputDirectory + 'HW8_box_55_salt_and_pepper_01.bmp')
stream.write('box 5x5 gaussian 10: ' + calculateSNR(inputMat, box55Gaussian10Mat) + '\n')
stream.write('box 5x5 gaussian 30: ' + calculateSNR(inputMat, box55Gaussian30Mat) + '\n')
stream.write('box 5x5 salt and pepper 0.05: ' + calculateSNR(inputMat, box55salt005Mat) + '\n')
stream.write('box 5x5 salt and pepper 0.1: ' + calculateSNR(inputMat, box55salt01Mat) + '\n')
// Median 3x3
let median33Gaussian10Mat = applyMedianFilter(gaussian10Mat, 3, 3)
let median33Gaussian30Mat = applyMedianFilter(gaussian30Mat, 3, 3)
let median33salt005Mat = applyMedianFilter(saltAndPepper005Mat, 3, 3)
let median33salt01Mat = applyMedianFilter(saltAndPepper01Mat, 3, 3)
median33Gaussian10Mat.save(outputDirectory + 'HW8_median_33_gaussian_10.bmp')
median33Gaussian30Mat.save(outputDirectory + 'HW8_median_33_gaussian_30.bmp')
median33salt005Mat.save(outputDirectory + 'HW8_median_33_salt_and_pepper_005.bmp')
median33salt01Mat.save(outputDirectory + 'HW8_median_33_salt_and_pepper_01.bmp')
stream.write('median 3x3 gaussian 10: ' + calculateSNR(inputMat, median33Gaussian10Mat) + '\n')
stream.write('median 3x3 gaussian 30: ' + calculateSNR(inputMat, median33Gaussian30Mat) + '\n')
stream.write('median 3x3 salt and pepper 0.05: ' + calculateSNR(inputMat, median33salt005Mat) + '\n')
stream.write('median 3x3 salt and pepper 0.1: ' + calculateSNR(inputMat, median33salt01Mat) + '\n')
// Median 5x5
let median55Gaussian10Mat = applyMedianFilter(gaussian10Mat, 5, 5)
let median55Gaussian30Mat = applyMedianFilter(gaussian30Mat, 5, 5)
let median55salt005Mat = applyMedianFilter(saltAndPepper005Mat, 5, 5)
let median55salt01Mat = applyMedianFilter(saltAndPepper01Mat, 5, 5)
median55Gaussian10Mat.save(outputDirectory + 'HW8_median_55_gaussian_10.bmp')
median55Gaussian30Mat.save(outputDirectory + 'HW8_median_55_gaussian_30.bmp')
median55salt005Mat.save(outputDirectory + 'HW8_median_55_salt_and_pepper_005.bmp')
median55salt01Mat.save(outputDirectory + 'HW8_median_55_salt_and_pepper_01.bmp')
stream.write('median 5x5 gaussian 10: ' + calculateSNR(inputMat, median55Gaussian10Mat) + '\n')
stream.write('median 5x5 gaussian 30: ' + calculateSNR(inputMat, median55Gaussian30Mat) + '\n')
stream.write('median 5x5 salt and pepper 0.05: ' + calculateSNR(inputMat, median55salt005Mat) + '\n')
stream.write('median 5x5 salt and pepper 0.1: ' + calculateSNR(inputMat, median55salt01Mat) + '\n')
let closingThenOpeningSaltAndPepper005Mat = applyClosingThenOpening(saltAndPepper005Mat, kernel)
let closingThenOpeningSaltAndPepper01Mat = applyClosingThenOpening(saltAndPepper01Mat, kernel)
let closingThenOpeningGaussian30Mat = applyClosingThenOpening(gaussian30Mat, kernel)
let closingThenOpeningGaussian10Mat = applyClosingThenOpening(gaussian10Mat, kernel)
closingThenOpeningSaltAndPepper005Mat.save(outputDirectory + 'HW8_closing_then_opening_salt_and_pepper_005.bmp')
closingThenOpeningSaltAndPepper01Mat.save(outputDirectory + 'HW8_closing_then_opening_salt_and_pepper_01.bmp')
closingThenOpeningGaussian30Mat.save(outputDirectory + 'HW8_closing_then_opening_gaussian_30.bmp')
closingThenOpeningGaussian10Mat.save(outputDirectory + 'HW8_closing_then_opening_gaussian_10.bmp')
stream.write('closing then opening gaussian 10: ' + calculateSNR(inputMat, closingThenOpeningGaussian10Mat) + '\n')
stream.write('closing then opening gaussian 30: ' + calculateSNR(inputMat, closingThenOpeningGaussian30Mat) + '\n')
stream.write('closing then opening salt and pepper 0.05: ' + calculateSNR(inputMat, closingThenOpeningSaltAndPepper005Mat) + '\n')
stream.write('closing then opening salt and pepper 0.1: ' + calculateSNR(inputMat, closingThenOpeningSaltAndPepper01Mat) + '\n')
let openingThenClosingSaltAndPepper005Mat = applyOpeningThenClosing(saltAndPepper005Mat, kernel)
let openingThenClosingSaltAndPepper01Mat = applyOpeningThenClosing(saltAndPepper01Mat, kernel)
let openingThenClosingGaussian30Mat = applyOpeningThenClosing(gaussian30Mat, kernel)
let openingThenClosingGaussian10Mat = applyOpeningThenClosing(gaussian10Mat, kernel)
openingThenClosingSaltAndPepper005Mat.save(outputDirectory + 'HW8_opening_then_closing_salt_and_pepper_005.bmp')
openingThenClosingSaltAndPepper01Mat.save(outputDirectory + 'HW8_opening_then_closing_salt_and_pepper_01.bmp')
openingThenClosingGaussian30Mat.save(outputDirectory + 'HW8_opening_then_closing_gaussian_30.bmp')
openingThenClosingGaussian10Mat.save(outputDirectory + 'HW8_opening_then_closing_gaussian_10.bmp')
stream.write('opening then closing gaussian 10: ' + calculateSNR(inputMat, openingThenClosingGaussian10Mat) + '\n')
stream.write('opening then closing gaussian 30: ' + calculateSNR(inputMat, openingThenClosingGaussian30Mat) + '\n')
stream.write('opening then closing salt and pepper 0.05: ' + calculateSNR(inputMat, openingThenClosingSaltAndPepper005Mat) + '\n')
stream.write('opening then closing salt and pepper 0.1: ' + calculateSNR(inputMat, openingThenClosingSaltAndPepper01Mat) + '\n')
console.log('finished')
})
}
main()