RORK LABEN
MAX — Rork Max は iPhone・iPad・Apple Watch・Apple TV・Vision Pro 向けにネイティブの Swift アプリを生成します。Xcode を開かずに2クリックで App Store へ出せる構成ですWIDGET — Rork Max はゲーム・ウィジェット・ライブアクティビティにも対応します。React Native 一本だった守備範囲が Apple プラットフォーム側へ広がりましたFUND — Rork は a16z から280万ドルを調達しました。月間訪問はおよそ743,000で、伸び率は85%とされていますMAESTRO — Expo が Maestro の E2E テスト実行向けにインサイトダッシュボードを追加しました(7月20日)。チーム全体の実行時間の推移を追えますCICD — Posh の事例として、EAS Workflows・フィンガープリント・Expo Updates で CI/CD を組み直した記録が7月23日に公開されましたSIRI — iOS 27 のパブリックベータが7月13日に始まりました。生成 AI ベースの新しい Siri は A17 Pro 以降・メモリ8GB以上が条件ですMAX — Rork Max は iPhone・iPad・Apple Watch・Apple TV・Vision Pro 向けにネイティブの Swift アプリを生成します。Xcode を開かずに2クリックで App Store へ出せる構成ですWIDGET — Rork Max はゲーム・ウィジェット・ライブアクティビティにも対応します。React Native 一本だった守備範囲が Apple プラットフォーム側へ広がりましたFUND — Rork は a16z から280万ドルを調達しました。月間訪問はおよそ743,000で、伸び率は85%とされていますMAESTRO — Expo が Maestro の E2E テスト実行向けにインサイトダッシュボードを追加しました(7月20日)。チーム全体の実行時間の推移を追えますCICD — Posh の事例として、EAS Workflows・フィンガープリント・Expo Updates で CI/CD を組み直した記録が7月23日に公開されましたSIRI — iOS 27 のパブリックベータが7月13日に始まりました。生成 AI ベースの新しい Siri は A17 Pro 以降・メモリ8GB以上が条件です
記事一覧/アプリ開発
アプリ開発/2026-07-29上級

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

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

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

プレミアム記事

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

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

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

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-07-18
1行も書かずに App Store 審査を一周する — ステッカーパックを申請の予行演習に使う
iMessage ステッカーパックはコードなしで App Store に提出できる数少ない枠です。収益にならない制約と引き換えに、申請工程を丸ごと一度通せます。画像仕様の落とし穴と、予行演習としての使い方をまとめました。
アプリ開発2026-07-07
App Store の新しい年齢別レーティングに答え直す — 複数アプリで実際に変わった項目とつまずき
13+/16+/18+ が加わった新しい年齢別レーティングの質問に、運用中のアプリで答え直したときの記録です。4つの新カテゴリ、最低年齢の引き上げ、Rork で公開したアプリでの実務をまとめました。
アプリ開発2026-06-30
Rork アプリでファイルを「その場で見せる」— Quick Look をアプリから安全に呼ぶ設計
PDF や画像、Office 文書をアプリの外に出さずにその場で見せる、Quick Look(QLPreviewController)をRork(Expo)から呼ぶ設計です。リモートファイルの事前ダウンロード、ローカル URL の条件、Android の FileProvider 代替、共有ボタンの扱いまで実装手順でまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →