Edited at

ProcessingでQRコードを使う


はじめに

この記事はProcessing Advent Calendar 2017 24日目の記事です。

そういえば24日ってクリスマスイブですね。

何も考えずに参加したので、クリスマス感は薄い記事になると思います。


ProcessingでQRコードを使う

ProcessingでQRコードを使う為のライブラリは有名なところだと、

Daniel Shiffmanのqrcode-processingがあります。

ですが今回はZXingP5という、Java製のQRコードライブラリZXingのProcessingラッパーを使います。

このライブラリの特徴はQRコードの左上、右上、左下にある四角形の座標が取得できることです。

なのでこのようにQRコードの位置と大きさ、角度や文字情報などを取得することができます。

実はこのライブラリは自分が作ったので、コメントやIssueをいただけたら、

修正や改良をしたいと思います。

sample

ではでは使い方を書いていきます。


インストール

ここからZipをダウンロードして、解凍したディレクトリをZXingP5にリネームして、PROCESSING_PATH/libraryに配置、

もしくはターミナルで以下のコマンドを実行します。

cd PROCESSING_PATH/library

git clone https://github.com/enkatsu/ZXingP5.git


使い方

サンプルは3つ入っていて内容はこのようになっています。


  • WriterSample...文字列からQRコードのPImageを生成するサンプル

  • ReaderSample...QRコードの映ったPImageから文字列を読み取るサンプル

  • ReaderAdvancedSample...QRコードの映ったPImageから文字列と座標、大きさを読み取るサンプル

一つずつ説明しようと思ったんですが、

見直してみたら説明するほどコード量が多くないので、

ReaderAdvancedSampleをいじってクリスマスっぽくしようと思います。

元のReaderAdvancedSampleはこんな感じです。

import processing.video.*;

import com.github.endoh0509.zxingp5.*;

Capture cam;
QRReader reader;

void setup() {
size(320, 240);

cam = new Capture(this, 320, 240);
cam.start();
reader = new QRReader(this);
}

void draw() {
if (cam.available() == true) {
cam.read();
image(cam, 0, 0);
tint(255, 200);
String txt = reader.decode(cam);
if (txt != null) {
PVector[] points = reader.getPoints();
PVector lowerLeft = points[0];
PVector upperLeft = points[1];
PVector upperRight = points[2];

// Get QR Code position
PVector vec = PVector.sub(lowerLeft, upperRight);
PVector center = PVector.mult(vec, 0.5).add(upperRight);

// Get QR Code angle
PVector qrVertical = PVector.sub(upperLeft, lowerLeft);
PVector camVertical = new PVector(0, 1);
float angle = atan2(qrVertical.y - camVertical.y, qrVertical.x - camVertical.x);
if (angle < 0) {
angle += TWO_PI;
}

// Get QR Code scale
float scale = PVector.dist(upperLeft, upperRight);

noStroke();
fill(255, 200);
rectMode(CENTER);
pushMatrix();
translate(center.x, center.y);
rotate(angle);
rect(0, 0, scale, scale);
popMatrix();

textAlign(CENTER, CENTER);
textSize(scale);
fill(#193EA2);
text(txt, center.x, center.y);
}
}
}

QRコードが読み取れた時だけ、

最初に載せた写真のように、

QRコードの位置と大きさ、角度を使って四角形を描画して、

その上に文字情報を表示しています。

これに画像をURLからロードしてくる感じにするとこんな風になります。

import processing.video.*;

import com.github.endoh0509.zxingp5.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Capture cam;
QRReader reader;
PImage img;

void setup() {
size(320, 240);
imageMode(CENTER);
cam = new Capture(this, 320, 240);
cam.start();
reader = new QRReader(this);
img = null;
}

void draw() {
if (cam.available() == true) {
cam.read();
image(cam, width / 2, height / 2);
String url = reader.decode(cam);
if (url != null) {
if (img == null && isImageURL(url)) {
img = loadImage(url);
} else if (img != null) {
PVector[] points = reader.getPoints();
PVector lowerLeft = points[0];
PVector upperLeft = points[1];
PVector upperRight = points[2];

// Get QR Code position
PVector vec = PVector.sub(lowerLeft, upperRight);
PVector center = PVector.mult(vec, 0.5).add(upperRight);

// Get QR Code angle
PVector qrVertical = PVector.sub(upperRight, upperLeft);
PVector camVertical = new PVector(0, 1);
float angle = atan2(qrVertical.y - camVertical.y, qrVertical.x - camVertical.x);
if (angle < 0) {
angle += TWO_PI;
}

// Get QR Code scale
float scale = PVector.dist(upperLeft, upperRight);

pushMatrix();
translate(center.x, center.y);
rotate(angle);
image(img, 0, 0, scale, scale);
popMatrix();
}
}
}
}

boolean isImageURL(String urlStr) {
String pattern = "(http(s?):/)(/[^/]+)+" + "\\.(?:jpg|gif|png)";
Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(urlStr);
return m.find();
}

スクリーンショット 2017-12-21 22.33.11.png

使ったQRコードはこちらです。

(実際に使ったのとQRのバージョンが違うから少し違いますが)

だいぶクリスマスっぽくなりましたね。

QR_Code1513877100.png

ではではメリークリスマス。

そして良いお年を。