- QRコードに偶然生じうるスワスティカ模様を検出し、任意で模様のないQRコードを生成するRustクレート
- QR標準の8種類のマスクパターンをすべてレンダリングして模様のない候補を絞り込み、ISO/IEC 18004のペナルティが最も低いマスクを選択する
- ファインダー・タイミング・アライメント・フォーマット・バージョンの各モジュールを検査から除外し、周囲とのコントラストを考慮することで、機能要素や目に見えない形状を誤認しないようにする
- デフォルトの検出器は外部依存がなく、
unsafeコードを禁止しており、複数のQRライブラリとVec<Vec<bool>>表現をサポートする - 検出範囲は軸に沿った5×5・7×7の鉤十字形の両方向と2種類の色極性に限定され、45度・対角線状の形状や任意回転はサポートしない
偶発的な模様を避けるべき理由
- qr-swastika-avoiderは、QRコードにランダムに現れうるスワスティカパターンを検出して回避する
- QRコードは相互に置き換え可能な8種類のマスクパターンのうち可読性スコアが最も良いものを選ぶが、不快感を与えうる記号までは検査しない
- 小さく細い模様はQR標準の評価過程で除外されにくく、最終的なコードに偶然残る可能性がある
機能要素とコントラストを考慮した検出
- デフォルトの検出器は外部依存がなく、
#![forbid(unsafe_code)]を適用している - 2つのメソッドで構成される小さな
QrModulesトレイトを通じて、さまざまなQR表現形式を検査できる - ファインダー・タイミング・アライメント・フォーマット・バージョンの各モジュールを検出対象から除外し、ファインダーの角をスワスティカと誤認しない
- 同じ色のモジュール内に埋もれて実際には見えない模様は、周囲とのコントラストを基準に無視し、この基準は調整可能
- 既存のQRコードは
contains_swastikaで検査でき、模様が見つかった場合は再生成したりユーザーに警告したりできる
サポートするQR表現とライブラリ
- Cargo機能として次のアダプターを提供する
qrcodegen:qrcodegen::QrCode用のQrModulesqrcode:qrcode::QrCode用のQrModulesfast_qr:fast_qr::QRCode用のQrModules
- 生のモジュール行列である**
Vec<Vec<bool>>**も別途アダプターなしでサポートし、trueは暗いモジュールを意味する
模様のないQRコード生成
generate機能のencode_safeは、コンテンツと誤り訂正レベルを受け取り、模様のないスキャン可能なQRコードを返し、生成できない場合は明示的なエラーを返す- 生成過程では8種類のマスクをすべてレンダリングしたうえで、検出対象の模様がない候補だけを残す
- 残った候補のうちISO/IEC 18004のペナルティが最も低いマスクを返し、標準の可読性最適化を維持する
- 返り値の
matrix()でモジュール行列を取得し、mask()で選択されたマスクを確認できる
Cargo機能構成
- デフォルト機能には依存関係のない検出器のみが含まれる
qrcodegen、qrcode、fast_qr機能は各ライブラリ用のアダプターを追加するgenerate機能はqrcodegenを依存関係として取り込み、encode_safeを提供する
検出範囲とライセンス
- 古典的な軸に沿った鉤十字形のうち、5×5と7×7サイズ、両方向、明暗2種類の色極性を小さな許容誤差内で検出する
- 45度または対角線状の模様や、任意角度に回転した形状は検出範囲に含まれない
- MIT Licenseで配布されている
1件のコメント
Lobste.rs の意見
このプロジェクトは宗教的な卍文は避けるのに、肝心のナチスが使った鉤十字は避けない点が混乱を招く。ナチスの紋様は45度回転した形なのに、プロジェクトは「45度・対角線モチーフと任意回転は対象外」と明記している
QRコードで偶然生じる画像は解像度が低いため、むしろ回転していない形だけがランダムなピクセル模様ではなく卍として鮮明に認識される可能性が高い。そこに注目するのは合理的だ
また「ファインダー・タイミング・アライメント・形式およびバージョンモジュールは除外し、ファインダーの角を卍と誤認しない」とあるが、人がQRコードの中に不快な象徴を見たとき、そのピクセルがデータなのかタイミングパターンなのかで反応が変わることはないはずだ。ファインダーの角はただの四角形なのに、なぜわざわざ解析から除外する必要があるのかもわからず、掘れば掘るほど辻褄が合わないので、AIが雑に生成した成果物なのではと疑ってしまう
こんなプロジェクトが存在するという事実が悲しい。QRコードの中に不快な象徴が偶然現れることがあるなんて、考えたこともなかった
「単純なQRコードを作っていて、巨大なナチスの紋様がランダムに現れることなんて一体どれくらいあるのか?」を実際に計算してみた。QRコードが完全なランダムではない点はここでは無視する。
5×5 と 7×7 の卍を独立に見ると、それぞれ左右2方向、2極性、反転・通常形があり、合計8パターンになる。全パターン数は 5×5 で 2^25=3,300万、7×7 で 2^49=562兆 なので、卍を含む確率はそれぞれ 2.38e-7 と 1.42e-14 だ。QRコード内には 5×5 領域が289個、7×7 領域が225個あるため、ランダムなQRコード形状で卍が1つでも現れる総確率は約 0.00006、つまり 14,500 個に 1 個となる。9×9 以上も計算できるが、特定のピクセル組み合わせの確率が低すぎて結果に意味のある影響を与えない。残念ながらソースを見る限り、このプロジェクトはバイブコーディングで作られたようだが、計算自体は自分で手でやった
ここまで具体的なプロジェクトだと、背景にどんな経緯や冗談があるのか気になる。
ただ、Microsoft photoDNA の知覚ハッシュが、学習データに大量にある CSAM サムネイル格子にうまく対応できず、スプレッドシートと Minecraft の制作グリッドのスクリーンショットだけで Discord ユーザーのアカウントを停止させる など、欠陥だらけのAIが使われている状況を見ると、より汎用的な危険パターン回避ツールはかなり魅力的に見える
過去の問題を新しいやり方で繰り返すより、現実の問題を解決すべきだ。世の中にはこういうプロジェクトを面白がって受け取る、過度に敏感な人が多すぎる
データパターンで卍を避けるのが目的だとしても、Webページ自体に紋様を表示しているので、ドイツでは違法になりうるのか気になる
ドイツ連邦最高裁のその判決によれば、線を引いて消した卍は許容され、その他もコードがフィルタリングするパターンの見本として示されているだけなので、問題になる可能性は低そうだ
https://en.wikipedia.org/wiki/Strafgesetzbuch_section_86a