srifqi.github.io/experiment/bare/dip/smoothing.html

185 lines
5.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html>
<head>
<title>Image Smoothing - Experiments - srifqi</title>
<meta charset="utf-8">
<meta name="author" content="srifqi">
<meta name="description" content="An example of image smoothing (mean, Gaussian, and median filter) in digital image processing">
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">
<style>
noscript, .noscript {
background: #fff9cC2;
border: 4px solid #fff176;
border-radius: 4px;
display: block;
padding: 4px;
margin: 8px;
}
noscript, .noscript, noscript *, .noscript * {
font: 12px sans-serif !important;
}
body {
font: 16px sans-serif;
margin: 0 auto;
max-width: 800px;
overflow-x: hidden;
overflow-y: scroll;
width: 100%;
}
h1 {
text-align: center;
}
.equation {
text-align: center;
}
.figures {
margin: 24px 0;
text-align: center;
}
.figures img, .figures canvas {
display: inline-block;
height: 256px;
width: 256px;
}
@media (max-width: 832px) {
body {
margin: 0 8px;
width: calc(100% - 16px);
}
}
/* MathML compatibility */
body.no-mathml .eq-mathml {
display: none;
}
body.mathml .eq-image {
display: none;
}
.eq-image img {
background-color: white;
}
</style>
</head>
<body>
<h1 id="title">Image Smoothing</h1>
<noscript class="noscript">
For full functionality of this site, it is necessary to enable JavaScript.
Here are the <a href="https://www.enable-javascript.com/" target="_blank">
instructions how to enable JavaScript in your web browser</a>.
</noscript>
<article>
<h2>Mean/Box Filter</h2>
<p>Below is an example of mean filter (box filter).</p>
<p class="equation eq-mathml"><math><mfrac><mn>1</mn><mn>9</mn></mfrac> <mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable><mo>)</mo></mrow></math></p>
<p class="equation eq-image"><img src="smoothing-eq-1.png" height=75 style="height: 75px;"></p>
<div class="figures">
<img id=imgA src="noisy-photo.png">
<canvas id=cA width=256 height=256></canvas>
</div>
</article>
<article>
<h2>Gaussian blur</h2>
<p>Below is an example of Gaussian blur with <math><mn>σ</mn> <mo>=</mo> 1</math>.</p>
<p class="equation eq-mathml"><math><mfrac><mn>1</mn><mn>4.8976</mn></mfrac> <mrow><mo>(</mo><mtable><mtr><mtd><mn>0.3679</mn></mtd><mtd><mn>0.6065</mn></mtd><mtd><mn>0.3679</mn></mtd></mtr><mtr><mtd><mn>0.6065</mn></mtd><mtd><mn>1.0000</mn></mtd><mtd><mn>0.6065</mn></mtd></mtr><mtr><mtd><mn>0.3679</mn></mtd><mtd><mn>0.6065</mn></mtd><mtd><mn>0.3679</mn></mtd></mtr></mtable><mo>)</mo></mrow></math></p>
<p class="equation eq-image"><img src="smoothing-eq-2.png" height=75 style="height: 75px;"></p>
<div class="figures">
<img id=imgB src="noisy-photo.png">
<canvas id=cB width=256 height=256></canvas>
</div>
</article>
<article>
<h2>Median filter</h2>
<p>Below is an example of median filter. Median filter works best for salt-and-pepper noises.</p>
<div class="figures">
<img id=imgC src="salt-and-pepper.png">
<canvas id=cC width=256 height=256></canvas>
</div>
</article>
<script>
const SIZE = 256;
const aA = cA.getContext("2d");
const aB = cB.getContext("2d");
const aC = cC.getContext("2d");
var imgData1, imgData2;
const Gauss = [
[0.3679, 0.6065, 0.3679],
[0.6065, 1.0000, 0.6065],
[0.3679, 0.6065, 0.3679]
];
window.addEventListener("load", function() {
aA.drawImage(imgA, 0, 0);
imgData1 = aA.getImageData(0, 0, SIZE, SIZE);
let canvasDataA = new ImageData(new Uint8ClampedArray(imgData1.data), imgData1.width, imgData1.height);
for (let j = 1; j < canvasDataA.height - 1; j ++) {
for (let i = 1; i < canvasDataA.width - 1; i ++) {
let k = (j * canvasDataA.width + i) * 4;
let sum = 0;
for (let y = -1; y <= 1; y ++)
for (let x = -1; x <= 1; x ++)
sum += imgData1.data[((j + y) * canvasDataA.width + i + x) * 4];
sum /= 9;
canvasDataA.data[k ] = sum;
canvasDataA.data[k + 1] = sum;
canvasDataA.data[k + 2] = sum;
}
}
aA.putImageData(canvasDataA, 0, 0);
let canvasDataB = new ImageData(new Uint8ClampedArray(imgData1.data), imgData1.width, imgData1.height);
for (let j = 1; j < canvasDataB.height - 1; j ++) {
for (let i = 1; i < canvasDataB.width - 1; i ++) {
let k = (j * canvasDataA.width + i) * 4;
let sum = 0;
for (let y = -1; y <= 1; y ++)
for (let x = -1; x <= 1; x ++)
sum += imgData1.data[((j + y) * canvasDataB.width + i + x) * 4] * Gauss[y + 1][x + 1];
sum /= 4.8976;
canvasDataB.data[k ] = sum;
canvasDataB.data[k + 1] = sum;
canvasDataB.data[k + 2] = sum;
}
}
aB.putImageData(canvasDataB, 0, 0);
aC.drawImage(imgC, 0, 0);
imgData2 = aC.getImageData(0, 0, SIZE, SIZE);
let canvasDataC = new ImageData(new Uint8ClampedArray(imgData2.data), imgData2.width, imgData2.height);
for (let j = 1; j < canvasDataC.height - 1; j ++) {
for (let i = 1; i < canvasDataC.width - 1; i ++) {
let k = (j * canvasDataA.width + i) * 4;
let list = new Uint8ClampedArray(9);
let idx = 0;
for (let y = -1; y <= 1; y ++)
for (let x = -1; x <= 1; x ++)
list[idx ++] = imgData2.data[((j + y) * canvasDataC.width + i + x) * 4];
list.sort();
canvasDataC.data[k ] = list[4];
canvasDataC.data[k + 1] = list[4];
canvasDataC.data[k + 2] = list[4];
}
}
aC.putImageData(canvasDataC, 0, 0);
});
// Change to image for those who does not support MathML
// https://stackoverflow.com/a/28835508
(function() {
let uaCheck = navigator.userAgent.match(/Chrome\/[0-9]+/);
if (uaCheck != null && uaCheck.length == 1 ||
!document.implementation.hasFeature("org.w3c.dom.mathml")) {
document.body.className = "no-mathml";
console.log("No MathML support these days?");
} else if (document.implementation.hasFeature("org.w3c.dom.mathml"))
document.body.className = "mathml";
})();
</script>
</body>
</html>