⛳
getUserMedia のカメラ映像の向きでハマった話(バーコード読み取り)
はじめに
MacBook Air でバーコードを読み取る Web アプリを作っていたところ、カメラでバーコードがまったく読めず苦戦したので、その備忘録です。
同じことで詰まった人の参考になれば幸いです。
やったこと
- Vue + ZXing で、カメラ映像からバーコードを読み取る Web アプリを作成した
- 読み取れなかったため、カメラ映像を 0° / 90° の2方向に回転した画像を順に ZXing に渡す実装に変更した
技術スタック
- Vue 3.4.0
- @zxing/library 0.20.0
実装のポイント(詰まったところ)
getUserMedia で得られる映像の向きは、端末・ブラウザ(Safari)等の環境によって異なるようです。
そのまま(0°)の画像では読めない場合があるため、0° → 90°の順に回転した画像を試し、最初にデコードできた向きの結果を使うようにしました。
方針
-
<video>に流している生のフレームを、Canvas に描画する際に回転させる - 0° / 90° の2パターンを毎フレーム順に試し、最初に ZXing がデコードできた結果を採用する
- 回転は Canvas 2D の
translateとrotateで実施
実際のコード
function drawVideoToCanvasWithRotation(video, canvas, deg) {
const w = video.videoWidth
const h = video.videoHeight
const cw = deg === 90 ? h : w
const ch = deg === 90 ? w : h
canvas.width = cw
canvas.height = ch
const ctx = canvas.getContext('2d')
if (!ctx) return
ctx.save()
if (deg === 90) {
ctx.translate(h, 0)
ctx.rotate(90 * (Math.PI / 180))
ctx.drawImage(video, 0, 0, w, h, 0, 0, w, h)
} else {
ctx.drawImage(video, 0, 0, w, h, 0, 0, w, h)
}
ctx.restore()
}
まとめ
明確な原因は特定できていませんが、getUserMedia で得られる映像の向きは、端末・ブラウザ(Safari)等の環境によって回転していることがあるようです。
「MacBookのカメラはスペースの都合で横向きに設置されており、プログラムでそのまま映像を取得すると回転した画像になってしまう」と自分なりに解釈していますが、公式の情報は見つけられず、原因の特定には至っていません。
バーコード読み取りがうまくいかない場合は、映像を複数方向に回転して試すと改善するかもしれません。
初めての技術記事でしたが、最後まで読んでいただきありがとうございました。
もし間違いや「ここはこうなっている」などのご指摘があれば、コメントで教えていただけると泣いて喜びます。
Discussion