Skip to content

Instantly share code, notes, and snippets.

@makenowjust
Last active August 29, 2015 14:25
Show Gist options
  • Select an option

  • Save makenowjust/ad5f71c9ae489fb5fcf0 to your computer and use it in GitHub Desktop.

Select an option

Save makenowjust/ad5f71c9ae489fb5fcf0 to your computer and use it in GitHub Desktop.
線密度イコライゼーション
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>線密度イコライゼーション</title>
</head>
<body>
<h1>equalization</h2>
<section>
<canvas id="canvas"></canvas>
<input type="button" id="w_up" value="+">
<input type="button" id="w_down" value="-">
<input type="button" id="clear" value="clear">
<input type="button" id="equalize" value="equalize">
<canvas id="output"></canvas>
</section>
<style>
canvas {
width: 300px;
height: 300px;
border: solid black 1px;
/* 実サイズより大きく見せるときにアンチエイリアスがかかってしまうのを抑制 */
image-rendering:optimizeSpeed; /* Legal fallback */
image-rendering:-moz-crisp-edges; /* Firefox */
image-rendering:-o-crisp-edges; /* Opera */
image-rendering:-webkit-optimize-contrast; /* Safari */
image-rendering:optimize-contrast; /* CSS3 Proposed */
image-rendering:crisp-edges; /* CSS4 Proposed */
image-rendering:pixelated; /* CSS4 Proposed */
-ms-interpolation-mode:nearest-neighbor; /* IE8+ */
}
</style>
<script src="index.js"></script>
</body>
</html>
(function (global) {
'use strict';
// グローバル的な変数達
var
// キャンバスの幅と高さ
W = 300, H = 300,
// 出力するキャンバスの幅と高さ
W2 = 32, H2 = 32;
var
down = false, // マウスのボタンが押されているかどうか
x = 0, y = 0, // 線を引く開始位置
// メインのキャンバスとコンテキスト
canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
// 出力用のキャンバスとコンテキスト
output = document.getElementById('output'),
out_ctx = output.getContext('2d');
// 幅と高さを設定
canvas.width = W;
canvas.height = H;
output.width = W2;
output.height = H2;
// 線を引くときの設定
ctx.lineWidth = 10;
ctx.lineCap = 'round';
// お絵描きする部分
// マウスが押されたとき
canvas.addEventListener('mousedown', function (e) {
down = true;
x = e.offsetX; y = e.offsetY;
});
// マウスが離されたとき
canvas.addEventListener('mouseup', function (e) {
down = false;
});
// マウスが動いたとき
canvas.addEventListener('mousemove', function (e) {
if (down) {
line(e.offsetX, e.offsetY);
}
});
// 「+」ボタンが押されたとき
document.getElementById('w_up').addEventListener('click', function () {
ctx.lineWidth = ctx.lineWidth + 1;
});
// 「-」ボタンが押されたとき
document.getElementById('w_down').addEventListener('click', function () {
ctx.lineWidth = Math.max(1, ctx.lineWidth - 1);
});
// 「clear」ボタンが押されたとき
document.getElementById('clear').addEventListener('click', function () {
clear();
});
// キャンバスの内容を消去する
function clear() {
ctx.clearRect(0, 0, W, H);
}
// 線を引く
function line(nx, ny) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x = nx, y = ny);
ctx.stroke();
}
// 線密度イコライゼーションするところ
// 「equalize」ボタンが押されたとき
document.getElementById('equalize').addEventListener('click', function () {
// TODO: 説明する
var
data = ctx.getImageData(0, 0, W, H),
bindata = binarize(data),
hx = densityXs(bindata, 0),
hy = densityYs(bindata, 0),
i, j, i1 = 0, j1 = 0, k,
new_is = [], new_js = [],
nx = 0,
ny = 0,
hx_sum = 0,
hy_sum = 0,
out_data = out_ctx.createImageData(W2, H2);
for (i = 0; i < W; i++) {
nx += hx[i];
}
for (j = 0; j < H; j++) {
ny += hy[j];
}
for (i = 0; i < W2 + 1; i++) {
for (; i1 < W && hx_sum < (i - 0.5) * nx / (W2 + 1); i1++) {
hx_sum += hx[i1];
}
new_is.push(i1);
}
for (j = 0; j < H2 + 1; j++) {
for (; j1 < H && hy_sum < (j - 0.5) * ny / (H2 + 1); j1++) {
hy_sum += hy[j1];
}
new_js.push(j1);
}
for (j = 0; j < H2; j++) {
for (i = 0; i < W2; i++) {
k = (j * H2 + i) * 4;
if (bindata[new_js[j + 1] + 1][new_is[i + 1] + 1]) {
out_data.data[k + 3] = 255;
}
}
}
out_ctx.putImageData(out_data, 0, 0);
});
function binarize(data) {
var
w = data.width, h = data.height,
i, j,
bindata = [];
bindata.push([]);
for (i = 0; i < w + 2; i++) {
bindata[0][i] = 0;
}
for (j = 0; j < h; j++) {
bindata.push([0]);
for (i = 0; i < w; i++) {
bindata[j + 1][i + 1] = +(data.data[(j * w + i) * 4 + 3] !== 0);
}
bindata[j + 1].push(0);
}
bindata.push([]);
for (i = 0; i < w + 2; i++) {
bindata[h + 1][i] = 0;
}
return bindata;
}
function densityX(bindata, i, alpha) {
var
h = bindata.length,
j,
density = alpha;
for (j = 1; j < h; j++) {
density += !bindata[j - 1][i] * bindata[j][i];
}
return density;
}
function densityXs(bindata, alpha) {
var
w = bindata[0].length,
i,
densities = [];
for (i = 1; i < w - 1; i++) {
densities.push(densityX(bindata, i, alpha));
}
return densities;
}
function densityY(bindata, j, alpha) {
var
w = bindata[0].length,
i,
density = alpha;
for (i = 1; i < w; i++) {
density += !bindata[j][i - 1] * bindata[j][i];
}
return density;
}
function densityYs(bindata, alpha) {
var
h = bindata.length,
j,
densities = [];
for (j = 1; j < h - 1; j++) {
densities.push(densityY(bindata, j, alpha));
}
return densities;
}
})((this || 0).self || global);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment