著者:Kodak_20
忙しい人のためのまとめ(この記事の結論)
-
何をしたか
QRコードの仕組みを完全に理解するため、ライブラリに頼らずゼロから読み取りロジックの実装に挑戦。
(※ただし「誤り訂正」の数学が難しすぎたため、検証用の最強リーダーにはOpenCVを使用しました……悔しい!) -
検証企画:落書き限界チャレンジ
「誤り訂正機能」を極限まで試すため、QRコードを物理的に汚して「どこまでなら読み取れるか」を検証 -
分かったこと(技術的知見)
どれだけ汚れていても読み取れる強さがある一方、「ファインダーパターン(隅の四角)」と「タイミングパターン(点線)」という2つの急所が欠損すると、たとえ汚れが誤り訂正の許容範囲内でもでも即死することがあると判明 -
結論と今後
QRコードには「直せるデータ」と「直せない構造」がある。
今回は既存ライブラリに敗北したが、必ず数学を勉強し直して完全自作でリベンジしたい -
注意
実機展示について、本アプリは検証用に作ったためUI/UX観点からみると終わっています
ご了承ください
はじめに
皆さん、QRコードって知ってますよね。(というか知らない人はいないと思います笑)
でも、「どういう仕組みなのか」を知っている人は実際かなり少ないはずです。
本記事では、QRコードに興味を持った僕が**趣味で作った「自作リーダー」が、学年代表として展示されることになったので、その開発の裏側を紹介します。
学祭展示来てる人へ
初めに言っておきます。この記事を読まないと実機、何も面白くないし、なんで選ばれたんとなります。
ターゲット
開発経緯
きっかけは、QuizKnockがYouTubeで公開していた「QRコードを目視で読む」という衝撃的な動画です。
非常に面白い企画でしたが、動画を見ているうちに「ここの処理はどうなっているのか?」「なぜ、あんな断片的な情報で読めるのか?」という疑問が次々と湧いてきました。
そこで、QRコードの仕組みについて詳しく調べてみることにしました。
参考にした文献
💡 今回の学び:QRコードの裏側にある技術
記事を読み解く中で、QRコードには大きく分けて4つの面白い仕組みがあるとわかりました。
1. データ格納の仕組み
QRコードは単なる模様ではなく、デジタルデータを視覚的に「翻訳」したものである。
-
基本は2進数:黒を
1、白を0として扱う -
変換プロセス:
- 読み取り順序やマスク処理(読み取りやすくする加工)のルールに従う
- 白黒の配置を数値(2進数)に置き換える
- それを8ビット区切りで束ねる
- UTF-8などの文字コード表と照らし合わせることで、URLや文字が復元される
2. 誤り訂正機能(Error Correction)
QRコードが多少汚れていたり、カメラがブレていたりしても読み取れるのには明確な理由がある。
「誤り訂正」という機能
コードの一部が破損・欠損していても、残った情報から計算してデータを自動的に補填・修復する仕組みが備わっている。
3. QRコードが汚れなどに強い理由
QRコードにはこの「誤り訂正機能」が備わっているため、汚れや破損に強い。しかし、この機能は魔法のように万能なわけではなく、設定されたレベル(強度)と、汚れが付着する位置という2つの要素に左右される。
① 誤り訂正レベル(Error Correction Level)
QRコード作成時に、どの程度まで破損を許容するかを4段階で設定できる。レベルを上げれば頑丈になるが、その分コード内の冗長データが増えるため、QRコードの目が細かくなる。
| レベル | 復元能力(目安) | 特徴 |
|---|---|---|
| L | 約 7% | データ量が少なく、見た目がすっきりする |
| M | 約 15% | 一般的によく使われる標準レベル |
| Q | 約 25% | 信頼性を少し高めたい場合 |
| H | 約 30% | 工場や屋外など、汚れる前提の場所向け |
この機能により、ポスターが雨で汚れたり、印刷が一部擦れてしまったりしても、正しくデータを読み取ることができる。
② 致命的な「位置」の存在
「30%まで直せる」といっても、どこでも良いわけではない。
破損する部位によっては、たとえ汚れの総面積が許容範囲内であっても、読み取り不能になる場合が存在する。
疑問と目的
以上の情報を整理する中で、私はある一点に強い違和感を覚えました。
「誤り訂正の許容範囲内でも、破損する部位によっては読み取り不能になる」
これでは、誤り訂正機能の意味がないのではないか?
あるいは、「消えてもいい場所」と「絶対に消えてはいけない場所」には明確な法則があるのだろうか?
幸運なことに、今はちょうど個人製作の期間と重なっている。
「それなら、自分で作って確かめてみよう」
私はQRコードの仕組みを肌で理解するためにリーダー(読み取り機)を自作し、自分の手で検証してみようと思い立ちました。
開発環境・使用ツール
今回の検証には、以下の環境を使用しました。
- エディタ: VS Code
- 言語: Python
- ライブラリ: OpenCV
実は、OpenCVには元々QRコードを検知して読み取るための便利なメソッド(QRCodeDetectorなど)が標準装備されています。
これを使えば数行で終わる話なのですが、当時の僕はこう思ってしまいました。
「メソッドとして存在するということは、裏にロジックがあるということ。なら、ライブラリに頼らず自分でもゼロから組めるんじゃね?」
この時の僕は、「既存メソッド=答え」であり、それを使わずに実装することこそが真の理解だと信じて疑わない、浅はかな希望を抱いていたのです。
立ちはだかる「誤り訂正」の壁
開発序盤は順調でした。
画像の白黒を判定し、0と1に変換する。ここまでは「画像処理」の世界なので、なんとか実装できました。
しかし、「誤り訂正」の実装フェーズに入った途端、開発の手が止まりました。
QRコードの誤り訂正に使われている「リード・ソロモン符号」などの数学的アルゴリズム。
解説記事を読んで「なるほど、ガロア体ね、多項式ね、完全に理解した(わかってない)」状態にはなれるのですが、それを具体的なプログラムコードに落とし込む作業が想像を絶する難易度でした。
自分の数学的理解度の浅さが露呈し、コードを書けば書くほどバグが増殖していく地獄。
「数学の強さ」を証明するつもりが、「数学の難しさ」に返り討ちにされる日々が続きました。
達成と挫折、そして決断
数日間の格闘の末、なんとか自作の誤り訂正ロジックらしきものは完成しました。
しかし、出来上がったのは……
- 綺麗なQRコードなら読める
- 誤り訂正は機能しているが既存のものに比べると明らかに精度が低いもの
という、「エラー訂正機能を検証するためのツールなのに、エラーに弱い」という本末転倒な代物でした。精度として正直お粗末すぎて、とても「限界チャレンジ」なんてできるレベルではありません。
そして、刻一刻と迫るクラス発表の日。
残り時間はあと1日。
このまま精度の低い自作リーダーで「すみません、読めませんでした」と発表するか。
それとも、プライドを捨てて「最強の剣」を借りるか。
私は決断しました。
「検証(展示)には、OpenCVの公式メソッドを使おう」
悔しいですが、先人たちが作り上げたライブラリの偉大さをこれほど痛感した日はありません。
心機一転:検証の方針変更
前述の通り、自作QRコードリーダー自体は完成しました。
しかし、今回の発表のメインテーマはあくまで「QRコードの汚損に対する強さ(限界)を検証すること」です。
自作リーダーは精度が不安定で、検証用ツールとしては信頼性に欠けると判断しました。
そこで、検証および展示の実演には、OpenCVの公式メソッド(QRCodeDetector)で作成した高精度なリーダーを採用することにしました。
検証結果:読み取れない「魔のパターン」
「最強の剣(OpenCV)」を使って限界まで汚してみたところ、興味深い事実が判明しました。
「誤り訂正の許容範囲(面積)内であるにも関わらず、読み込みに失敗する特定のパターンがある」
具体的には、以下の2箇所の情報が欠落すると、他の部分がどれだけ綺麗でも読み取れないことが多かったのです。
- タイミングパターン
- ファインダーパターン
考察:なぜそこが弱点なのか?
なぜ面積的にはセーフなのに、ここが汚れるとアウトなのか。
QRコードの構造的な役割から、私は以下のように考察しました。
1. タイミングパターンの欠損
→ 「セルの住所(座標)が特定できなくなる」
タイミングパターンとは、白と黒が交互に並んでいる点線のような部分です。
これは、カメラ画像上で「各セルの中心位置」を特定するための目盛り(グリッド)の役割を果たしています。
ここが汚れて読み取れなくなると、グリッドを正しく引くことができません。結果として、「データの取得位置がズレてしまい、正しいビット情報を拾えなくなる」ため、読み取り不能になると考えられます。
2. ファインダーパターンの欠損
→ 「QRコードとしてのアイデンティティを失う」
ファインダーパターンは、3つの隅にある大きな四角形(切り出しシンボル)です。
これには2つの重要な役割があります。
- 存在の証明: プログラムに「ここにQRコードがあるぞ」と認識させる
- 向きの特定: QRコードがどの向き(回転)になっているかを判別する
つまり、ここが欠損するということは、「そもそもQRコードとして認識されない」あるいは「上下左右がわからず解析不能になる」ということになります。誤り訂正以前の、門前払いの状態です。
結論:
QRコードには「直せるデータ領域」と「直せない構造領域」がある。
おわりに
今回の「QRコードリーダーの自作」と「限界検証」を通して、普段何気なく使っている技術の裏側に触れることができ、非常に有意義な時間を過ごせました。
ただ、やはり心残りなのは「自作誤り訂正ロジック」の敗北です。
理論は理解したつもりでも、それを実装として形にする難しさ、そして既存ライブラリの偉大さを痛感しました。検証のためにOpenCVに頼らざるを得なかった点は、正直かなり悔しいです。
このままでは終われません。
必ずリベンジして、今度こそ「完全自作の最強QRコードリーダー」を完成させ、また記事として公開したいと思います。(数学、勉強し直します……!)
長くなりましたが、最後まで読んでくださりありがとうございました!



