この前触った、WebNFC に味をしめて実験的な API を今後も触ってゆきたいと感じました。
今回は、バーコードの読み取りをしてみます。
目次
参考
Shape Detection API
Shape Detection API を使用すると、文字列・顔・バーコードの認識が可能になります。
用意
今回も、Experimental Web Platform feature
を有効化する必要があります。
WebNFC を試そう を参照して設定ください。
実装 1(画像の中のバーコードを読み取る)
読み取る対象の qr コードを表示する html は以下のようになります。
test1.html(QRコードの場合)1 2 3 4 5 6 7
| <html> <head> </head> <body> <img src="qr.png" id="source" /> <script type="text/javascript" src="app1.js"></script> </body> </html>
|
バーコードを読み取る場合、 html は以下のようになります。画像を差し替えるだけです。
test1.html(バーコードの場合)1 2 3 4 5 6 7
| <html> <head> </head> <body> <img src="code39.png" id="source" /> <script type="text/javascript" src="app1.js"></script> </body> </html>
|
処理する JavaScript は以下のようになります。
app1.js1 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
| const barcodeDetector = new BarcodeDetector();
const image = document.getElementById("source");
console.log(image); let code = null; (async () => { try { code = await barcodeDetector.detect(image); } catch { $("#result").text("ERROR"); }
if (code == null) { return; }
console.log(code);
let resultText = ""; for (const barcode of code) { resultText += ` <ul> <li>rawValue = ${barcode.rawValue}</li> <li>format = ${barcode.format}</li> <li>width = ${barcode.boundingBox.width}</li> <li>height = ${barcode.boundingBox.height}</li> <li>x = ${barcode.boundingBox.x}</li> <li>y = ${barcode.boundingBox.y}</li> </ul> `; } $("#result").html(resultText); })();
|
確認 1
こちらを、Android で動作させ確認します。
デバッグ方法は、WebNFC を試そう を参照して設定ください。
こちらを読み込むと次のように表示されます。
QR コードの場合
Code-39 の場合
Shape Detection API
を使用し、読み込むことのできる 1 次元 2 次元バーコードは、以下のものが記載されています。
作り方が悪かった可能性はあるのですが、読み取れないものもあったので以下に掲載します。
aztec
(作成する手段が見つからなかった)
code_128
(OK)
code_39
(OK)
code_93
(OK)
codabar
(OK NW-7 の別名が codebar 作成するときは、NW-7 を探すほうが楽)
data_matrix
(NG?)
ean_13
(OK JAN_13 として作成したバーコードは ean_13 として認識された)
ean_8
(OK JAN_8 として作成したバーコードは ean_8 として認識された)
itf
(OK)
pdf417
(OK)
qr_code
(OK)
upc_a
(OK)
upc_e
(OK)
ちなみに、1 次元バーコードを 90 度まわして動作確認してみましたが、しっかり読み取りできました。
実装 2 カメラから読み込む
画像からバーコードを読み取ったので、今度はカメラから取得してみます。
実装は以下の通りです。
test2.html1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <html> <head> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous" ></script> </head> <body> <div id="canvas_area"> <canvas id="result" width="300" height="300"></canvas> </div> <div id="result_text"></div> <script type="text/javascript" src="app2.js"></script> </body> </html>
|
app2.html1 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
| const barcodeDetector = new BarcodeDetector();
const image = document.createElement("video");
const offscreen_canvas = document.createElement("canvas"); const offscreen_context = offscreen_canvas.getContext("2d");
const canvas = document.querySelector("#result"); const context = canvas.getContext("2d");
offscreen_canvas.width = canvas.width; image.videoWidth = canvas.width; offscreen_canvas.height = canvas.height; image.videoHeight = canvas.height;
let code = null;
window.onload = async () => { const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: "environment" }, }, });
image.srcObject = stream; image.play();
analysis();
setInterval(() => { reflesh(); }, 800); };
const analysis = async () => { offscreen_context.drawImage(image, 0, 0);
try { code = await barcodeDetector.detect(image); } catch { window.requestAnimationFrame(analysis); return; }
let state = true;
if (code == null) { state = false; } if (state == true && code.length == 0) { state = false; }
if (state) { offscreen_context.strokeStyle = "rgb(255, 0, 0) "; offscreen_context.lineWidth = 10; offscreen_context.beginPath( code[0].cornerPoints[0].x, code[0].cornerPoints[0].y ); offscreen_context.lineTo( code[0].cornerPoints[1].x, code[0].cornerPoints[1].y ); offscreen_context.lineTo( code[0].cornerPoints[2].x, code[0].cornerPoints[2].y ); offscreen_context.lineTo( code[0].cornerPoints[3].x, code[0].cornerPoints[3].y ); offscreen_context.lineTo( code[0].cornerPoints[0].x, code[0].cornerPoints[0].y ); offscreen_context.closePath(); offscreen_context.stroke(); } context.drawImage(offscreen_canvas, 0, 0, canvas.width, canvas.height); window.requestAnimationFrame(analysis); };
const reflesh = () => { $("#result_text").empty(); if (code == null) { $("#result_text").text("ERROR"); return; } if (code.length == 0) { $("#result_text").text("ERROR"); return; } let resultText = ""; for (const barcode of code) { resultText += ` <ul> <li>rawValue = ${barcode.rawValue}</li> <li>format = ${barcode.format}</li> <li>width = ${barcode.boundingBox.width}</li> <li>height = ${barcode.boundingBox.height}</li> <li>x = ${barcode.boundingBox.x}</li> <li>y = ${barcode.boundingBox.y}</li> </ul> `; }
$("#result_text").html(resultText); };
|
確認 2
動作させてみました。
QR コードの場合
pdf417 の場合
カメラから取得した画像を基に、バーコードの値の読み取りと、枠を描くことができました。
今回、バーコードの読み取りをするにあたり対応するバーコードを一通り確認しました。
線と空白の羅列のように見えて規格がたくさんあるというのが 1 つの発見でした。
また、pdf417 規格のコードは「もう、バーコードに見えない。」「なんかかっこいい。」というのが、正直な感想でした。
次回は、(思い付きがなければ)顔の取得を試みてみます。
ではでは。