RORK LABEN
DEADLINE — Google Play は2026年8月31日以降、新規アプリと既存アプリの更新の双方に対象 API レベル36(Android 16)以上を要求します。残り13日ですEXTENSION — 期限に間に合わない場合は Play Console の期限延長フォームから申請することで11月1日まで配信を継続できます。延長は自動ではなく、申請自体を期限内に行う必要がありますTARGET SDK — Rork などのビルダーが出力する Expo / React Native アプリでも targetSdkVersion は自分で確認が必要です。テンプレートが古い SDK に固定されていると生成しただけでは要件を満たしませんPOLICY — スパムと最低限の機能に関するポリシーが改定され、高品質な機能とコンテンツ体験が求められます。薄いアプリを量産する運用は正面から影響を受ける領域ですPRIVACY — 収集するデータの項目・用途・第三者への共有の有無について詳細な説明が求められます。ビルダーが自動で組み込む解析 SDK や広告 ID も申告の対象ですRORK — 従来の Rork が React Native / Expo を出力するのに対し、Rork Max は SwiftUI を生成します。無料枠から始められ、有料プランは月25ドルからですDEADLINE — Google Play は2026年8月31日以降、新規アプリと既存アプリの更新の双方に対象 API レベル36(Android 16)以上を要求します。残り13日ですEXTENSION — 期限に間に合わない場合は Play Console の期限延長フォームから申請することで11月1日まで配信を継続できます。延長は自動ではなく、申請自体を期限内に行う必要がありますTARGET SDK — Rork などのビルダーが出力する Expo / React Native アプリでも targetSdkVersion は自分で確認が必要です。テンプレートが古い SDK に固定されていると生成しただけでは要件を満たしませんPOLICY — スパムと最低限の機能に関するポリシーが改定され、高品質な機能とコンテンツ体験が求められます。薄いアプリを量産する運用は正面から影響を受ける領域ですPRIVACY — 収集するデータの項目・用途・第三者への共有の有無について詳細な説明が求められます。ビルダーが自動で組み込む解析 SDK や広告 ID も申告の対象ですRORK — 従来の Rork が React Native / Expo を出力するのに対し、Rork Max は SwiftUI を生成します。無料枠から始められ、有料プランは月25ドルからです
記事一覧/アプリ開発
アプリ開発/2026-07-29上級

壁紙カタログに同じ絵が二度並んでいた — 知覚ハッシュの閾値を324枚で実測して決める

画像カタログの重複検出を、SHA-256・dHash・色相署名・ブロック署名の4通りで実測しました。dHash 単独では適合率0.9%。平坦な画像でハッシュが潰れる現象と、閾値ではなく正解ラベルの方が間違っていた顛末を、再現できるコードと数値で共有します。

画像処理4知覚ハッシュdHash重複検出アセット管理Node.js2sharp個人開発197

プレミアム記事

朝、自分の壁紙アプリのカタログ画面をスクロールしていて、指が止まりました。

同じ絵が、少し離れた位置に二度並んでいます。

片方は初期に入れたもの、もう片方は後から別バッチで追加したもの。ファイル名も追加日も違うので、これまで一度も気づきませんでした。個人開発で数千枚のアセットを扱っていると、こうした取りこぼしが静かに積み上がっていきます。

App Store のレビューで指摘されたわけではありません。それでも、お金を払って使ってくださっている方の画面に同じ絵が二度出るのは、避けたいところでした。

手作業で全部見比べる選択肢はありません。機械で見つける仕組みを入れることにしました。

その過程で、事前に思い描いていた設計は二度ひっくり返りました。以下、実際に測った数字とともに残しておきます。

検証セットを手元に切り出す

本番カタログをそのまま実験台にすると、結果を後から検証できません。挙動を数字で確かめられるよう、同じ性質を持つ検証セットを合成しました。

1290×2796(iPhone の縦解像度)の JPEG を160枚。中身はグラデーション・ぼかしたブロブ・ストライプ・ノイズ雲の4種類を40枚ずつ。壁紙カタログにありがちな構成をなぞっています。

そこから、意図的に5種類の派生を作りました。

派生の種類枚数正解の扱い
JPEG 品質92→74 で再エンコード54重複
1290×2796 → 828×1792 にリサイズ32重複
明度を6%上げる23重複
上下左右を2%クロップして戻す15重複
色相を80度回す40別物

合計324枚。最後の色相変種を「別物」に置いたところが、この検証の肝になります。壁紙アプリでは色違いこそが並べたい商品であって、統合されては困ります。

環境は Node 22.22.3 と sharp 8.18.3(libvips 経由)。以降の数字は全てこの構成での実測です。

SHA-256 から始めて、すぐ行き詰まる

最初に試したのはファイルのバイト列に対する SHA-256 でした。実装は数行で済みますし、まずは完全一致だけでも掃除できるはずと考えていました。

結果は、真の重複124組のうち検出できたのは3組。再現率2.4%です。

理由は考えてみれば当たり前でした。JPEG は再エンコードした時点でバイト列が変わります。リサイズも明度調整もクロップも同様です。バイト一致で拾えるのは「同じファイルを二度アップロードした」ケースだけで、そのケースはアップロード時のガードで既に潰してありました。

残っていたのはまさに「見た目は同じだがバイトは違う」ものばかりで、ハッシュの完全一致はその全てを素通りさせます。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
SHA-256 による完全一致は、再エンコードやリサイズを挟んだ124組の重複のうち3組しか拾えず再現率2.4%でした。バイト一致がなぜ役に立たないのかを数字で示します
dHash 単体を閾値10で回すと再現率97.5%・適合率0.9%(誤検出16,570組)。原因は元画像160枚のうち80枚が「情報量ゼロのハッシュ」に潰れていたことでした。popcount ゲートで誤検出が0組になるまでの過程を全て掲載します
自動統合・目視レビュー・別物の3バンドに分ける判定器の実装全文と、324枚 6.67秒(20.6 ms/枚)の実測。取りこぼし0組・自動統合帯の適合率96.9%まで詰めた設定値をそのまま使えます
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

アプリ開発2026-08-16
グラフが壊れて見えるのは、データが多いときではなく最初の数日でした
記録アプリの折れ線グラフが、データの少ない最初の数日だけ線が消える。原因はY軸の幅が0になり座標がNaNになることでした。実測した挙動と、描画前に置く小さな正規化層を紹介します。
アプリ開発2026-08-15
TestFlight の外部テストと段階公開、個人開発ではどちらに時間を使うか
Rork で作ったアプリを他人に配るとき、外部テスターを募集する道と段階公開に受け止めさせる道の二つがあります。個人開発の限られた時間をどちらに置くかを、配布が止まる条件と事前検証すべき三領域から整理しました。
アプリ開発2026-08-06
壁紙の上の文字が読めるかを、端末ではなく取り込み時に決める — 判定指標を4つ測り比べた記録
壁紙の上に置くステータスバーや見出しが読めるかを、端末での画像解析ではなく取り込み時のメタデータで決める設計です。240枚のコーパスで判定指標を4つ実測し、縮小画像での判定が何と一致するのかまで記録しました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →