LoginSignup
16
3

観光客向けに日本のプロ野球を中心としたコンシェルジュチケットサービスを運営しています。どんどん、チームは QRコードのチケットをますます採用しており、多言語対応のカスタムチケットを作成する可能性が開かれています。

例えば、次のチケットを考えてみましょう。

2023年5月4日阪神タイガースブリーズシートチケットの図

上は、英語翻訳を追加する前の典型的な阪神タイガースの電子チケットの外観です。

実現したいのは、顧客向けにチケット情報をデータベースに入力し、顧客向けには英語でモバイル端末に表示して、球場の案内係向けには日本語で表示できるようにしたいということです。現在、バックアップとして、次のようなよりわかりやすい方法でチケットを印刷しています。

翻訳された2023年5月4日の阪神タイガースブリーズシートチケットの図

手動で作成しているため、英語を追加したのオリジナルと非常によく似ています。それぞれチームは独自のデザインをしているので、同一形式なスタイルQRコードチケットを印刷できればいいなと思います。

そのためのに、QRコードの内容値を読み取れて、再現出力できる可能な方法を調べてみましょう。Livebookを利用して、それがどのように機能するかを理解してみましょうと試してみましょう。

QRコード遊び場

上記の QRコードをスキャンする場合は、その内容が 202302088808H19425 であることがわかります。よっし。しかし、画像を保存せずに、QRコードの読み取りと作成を自動化できるようにしたいと考えています。そのために、新しい Livebook を開いて、:evision:kino をインストールして、実験してみましょう。

Mix.install([
   {:evision, "~> 0.1.33"},
   {:kino, "0.11.0"}
])

次に、上記の最初のタイガース チケットの画像をLivebook の Files セクションの + Add File 領域にドラッグ アンド ドロップします。

ファイルを追加するの図

これにより、現在の Livebookセッションに添付ファイルとして追加されます。では、添付されたファイルを読み込んでみましょう。

alias Evision, as: Cv

Kino.FS.file_path("2023-05-04-han-breeze-35-97.png")
|> Cv.imread()

EvisionCv ("Computer Vision" のこと?) というエイリアスとしてよく使われるそうので、使用します。

添付された PNGファイルのパスを取得し、Evisionimread/1 関数にパイプするだけです。次のような結果が得られます。

電子チケットの画像を読み取るの図

次に、Cv.QRCodeDetector にパイプして、QRコードの内容を取得しましょう。

|> then(&Cv.QRCodeDetector.detectAndDecode(
   Cv.QRCodeDetector.qrCodeDetector(), &1))

画像内のQRコードを検出してデコードするの図

QRコードのデコードされた文字列がこの結果に表示されています。後で使用するために抽出しましょう。

alias Evision, as: Cv

{decoded_string, points, straight_qrcode} =
  Kino.FS.file_path("2023-05-04-han-breeze-35-97.png")
  |> Cv.imread()
  |> then(&Cv.QRCodeDetector.detectAndDecode(
    Cv.QRCodeDetector.qrCodeDetector(), &1))

decoded_string

画像を読み取り、QRコードを検出してデコードし、デコードされた文字列を出力しますの図

QRコードを出力する

これで、デコードされた QRコードの内容が得られ、ゲート、通路、列、座席番号とともにデータベースに保存できるようになりました。QRコード内容にその情報が含まれていると思いますが、それを解読することに興味はありません。QRコードを任意のサイズで再現して様々な方法で出力したいだけです。

そのためには、Evision モジュールを使用すると非常に簡単になります。

Cv.QRCodeEncoder.encode(Cv.QRCodeEncoder.create(), decoded_string)

デコードされた文字列からQRコードを作成するの図

これで QRコードを出力しましたがが、かなり見にくいです。小さすぎて、上の圧縮画像ではスキャンするはできないと思います。もう少し大きくで出力しましょう。

|> Cv.resize({300, 300})

生成された QRコードを拡大したの図

うまく大きくなりまして、スキャンするとは可能です。でも、なんだかぼやけてますね。このために特別に設計された画像補間アルゴリズムを使用して、もっとはっきり出力しましょう。

|> Cv.resize({300, 300}, interpolation: CV.Constant.cv_INTER_AREA())

生成された拡大QRコードを鮮明化の図

はるかに優れており、シャープです。実際、上記の翻訳されたチケットに使用した QRコードはこの作成されたより少しぼやけていることがわかります。このワークフローにより、任意のサイズで鮮明に出力できるようになります。

複雑な QRコード

タイガーズの QRコードはどれもシンプルでベーシックな QRコードです。他のほとんどすべての球団は、り複雑で大きな QRコードを使用しています。以下がスワローズの代表的なチケットです。

翻訳しました 2023年10月4日のヤクルトスワローズSSチケットの図

以上の画像を Livebookに添付して、試してみましょう。

{decoded_string, points, straight_qrcode} =
  Kino.FS.file_path("2023-10-04-yak-ss1-22-18.png")
  |> Cv.imread()
  |> then(&Cv.QRCodeDetector.detectAndDecode(
    Cv.QRCodeDetector.qrCodeDetector(), &1))

decoded_string

スワローズチケットのデコードされた文字列を取得するの図

よっし! ここまでは順調ですね。それでは、QRコードを再生成してみましょう。

Cv.QRCodeEncoder.encode(Cv.QRCodeEncoder.create(), decoded_string)
|> Cv.resize({300, 300}, 補間: Cv.Constant.cv_INTER_AREA())

再生された QRコードの図

うーん。QRコードを再作成しました。しかし、オリジナルの QRコードとは見えません。新しい QRコードをスキャンすると、同じデコードされた文字列になります。

"d34a78f948c92e681f66b34b7c34806eeaee98709e3ae76a69d620103d24fb37"

ちょっと Base 16でエンコードされた文字列のようです。UTF-8 またはシフト JIS でしょうか? いいえ、d34a は UTF-8で「퍊」の韓国語の文字であって、シフトJISの最初のバイトが 0xd3 であるものはありません。

じゃ、Base 16でエンコードされた文字列をバイトの配列に変換し、QRコードを生成して見てみましょう。

{decoded_string, points, straight_qrcode} =
  Kino.FS.file_path("2023-10-04-yak-ss1-22-18.png")
  |> Cv.imread()
  |> then(&Cv.QRCodeDetector.detectAndDecode(Cv.QRCodeDetector.qrCodeDetector(), &1))

decoded_string
|> Base.decode16!(case: :lower)
|> IO.inspect()
|> then(&Cv.QRCodeEncoder.encode(Cv.QRCodeEncoder.create(), &1))
|> Cv.resize({300, 300}, interpolation: Cv.Constant.cv_INTER_AREA())

デコード値の HEX デコード後に再生成されたスワローズ チケット QRコードの図

いやー。最初の QRコードから再生された QRコードにデータがすこじまばされたそうでしたが、もっとデータが減られたそうに見えます。

より大きな QR コードを機能させるには、さらに研究する必要があるようです。ここで何が起こっているのか知っている人がいたら、ぜひご意見をいただきたいです。

16
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
3