Canvas APIを使ってWebでグラフィックを描画したり加工したりする
 Author: mito.shimada

canvas APIとは

htmlのcanvas要素のこと。

<canvas id="canvas"></canvas>

canvasの上にはJavaScriptで制御して図形や絵を描画することができる。

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

ctx.fillStyle = 'green';
ctx.fillRect(10, 10, 150, 100);

上記の例では緑色の四角形が現れる。

fillStyleでこれから描写する図形の色を指定し、fillRectで長方形を描写している。

応用例

明度を上げる

canvasに表示されている画像の全ピクセルを取得し、rgbの全てにプラス10することで明度を上げる技。

const diff = 10
const pixels = canvasCtx.getImageData(0, 0, 640, 494)
const d = pixels.data
for (let i = 0; i < d.length; i += 4) {
  d[i] += diff // r
  d[i + 1] += diff // g
  d[i + 2] += diff // b
}
canvasCtx.putImageData(pixels, 0, 0)

デジタルでお化粧

今ちょうどsnowみたいなアプリを作っているとする。

インカメラで自撮りするとメイクアップされた顔が表示される。

canvasには絶え間なくユーザーのインカメラの映像が映し出されている。

そこにOpenCVなどで顔認識を走らせ、唇のLandmarks(座標)を取得し、色を付ける処理を実装したい。

唇のLandmarksはすでに取れているものとし、下記のように実装した。

デバッグ用に、どこにLandmarksのindex何番が表示されているのか知りたいので、indexも描画している。

const __fill = (canvasCtx, points) => {
  canvasCtx.beginPath()
  canvasCtx.moveTo(points[0].x, points[0].y)
  points.splice(0, 1)
  points.forEach((point, i) => {
    // pointを結ぶ線を引く。fill()で塗りつぶされる
    canvasCtx.lineTo(point.x, point.y)
    // pointの座標にindexの数字を配置する(デバッグ用)
    canvasCtx.fillText(i, point.x, point.y)
  })
  canvasCtx.fill()
}
const mouthLandmarks = [
  {x: 275.4868933089642, y: 330.9715563375305},
  {x: 282.46803207477615, y: 325.7225076276611},
  {x: 292.1396419831185, y: 320.55676439588774},
  {x: 299.4580142327218, y: 321.12185386007536},
  {x: 306.25136206826255, y: 317.9190892297577},
  {x: 321.9393919535546, y: 321.63006702249754},
  {x: 337.6620153017907, y: 323.5335417110275},
  {x: 325.27621345004127, y: 332.3888464290451},
  {x: 315.2544691391854, y: 338.6371144372772},
  {x: 304.66151045044944, y: 341.4427271205734},
  {x: 295.3428850599198, y: 341.4085681754898},
  {x: 285.4118543394475, y: 338.5544467288803}
]
canvasCtx.fillStyle = 'rgba(255,0,22,0.15)'
__fill(canvasCtx, mouthLandmarks)

参考

https://developer.mozilla.org/ja/docs/Web/API/Canvas_API