
2026/03/09 23:16
**画像のメインカラーを選ぶ方法** 1. **被写体を特定する** • 写真で最も重要な要素(人物・物体・風景)を確認します。 2. **支配的なトーンをチェックする** • 画像編集ツールで色ヒストグラムやパレットを表示させます。 • 最も頻繁に現れる色相をメモします。 3. **代表的なシェードを選ぶ** • 感情・雰囲気に合った支配色のうち、最適と思われる1色を決めます。 • 必要なら背景とのコントラストが十分か確認します。 4. **調和をテストする** • 選んだ色をアクセントやオーバーレイとして適用します。 • 彩度・明度を微調整し、画像全体のバランスが取れたら終了です。 5. **仕上げる** • メインカラーを強調した版を保存します。 • 比較用にオリジナルコピーも残しておきましょう。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Summary
Okmain は、知覚的に均一な Oklab 空間で色をクラスタリングすることで画像から「OK main」カラーを高速に抽出する Rust ライブラリです。画像は 250 k ピクセル以下になるまでダウンサンプリングされ、その後全データセットに対して最大 4 クラスターの K‑means++ を適用します(ミニバッチ k‑means は使用せず)。各ピクセルは画像中心からの距離で重み付けされ、中央部に位置し視覚的に目立つ色が強調されます。最も高い Oklab 色相(彩度)を持つクラスタがメインカラーとして返却されます。AVX2/SSE2 での SIMD 自動ベクトル化により、数百メガピクセル画像でも典型的には約 100 ms の実行時間です。Python ラッパーにより、開発者は PyPI または Rust の crates.io を通じて Okmain を利用できます。
著者は純粋なランダムサンプリング(ノイズを過剰に代表するため破棄)や高速だがバグの多いコードを生成した LLM エージェントを試しました。最終的には手動で実装を書き上げました。パフォーマンスチューニングでは、全データセットへの反復処理、K‑means++ 初期化、および Rust の安定した自動ベクトル化がまだ制限を持つホットスポットにおける可読性の注意深い扱いが含まれます。
プロジェクトは実用的なライブラリとして完結し、k‑means クラスタリング、SIMD 最適化、Python/Rust 混合リリース戦略、および LLM 補助開発の現実についての教訓を提供します。
本文
背景
あなたのアプリには画像付きカードがあります。
カードの裏面を「その画像を代表しつつ、かつ見た目もよい」単色にしたいと考えています。
ある企業では、画像全体を 1×1(1ピクセル)へリサイズして、そのピクセルの色を使用する手法を採用しました。
この方法は非常にシンプルで人気がありますが、オリジナル画像が鮮やかな色であっても、取得される色はしばしばくすんだり濁ったりします。
私は週末をかけて既存の手法を調査し、改善策を試行した結果、「Okmain」というライブラリを作成しました。
Oklab の命名にヒントを得て、主要色(OK main colour)を探すという意味で Okmain と呼びます。
取り入れたテクニック
- 色クラスタリング
- Oklab カラーモデルの計算
- クロマ + 位置に基づくクラスタソート
残りは Rust で実装し、Python ラッパーを作成して高速化・堅牢化、ドキュメント整備、crates.io と PyPI へのリリース、そしてブログ記事の執筆です。簡単ですね!
色クラスタリング
画像には多くの場合、複数の色クラスターが存在します。そのため「すべてのピクセルを平均化する」だけでは不十分です。
例として以下の画像を考えてみましょう。
緑いろのフィールドと青い空はそれぞれ美しい色ですが、単純に平均すると全体的に淡くなります(下図参照)。
そこで、似たような色同士をグループ化し、その中で平均化する方法を採用します。
k‑means はその目的に適したアルゴリズムです。
- すべてのピクセルの色情報だけを使い、位置は一時的に無視してクラスタリングします。
- Okmain では最大で 4 クラスター を許容しました。テスト上で十分な品質が得られ、クラスター数を制限することで計算コストも抑えられます。
以下は色クラスタリング後の画像(クラスタごとのスウォッチ付き)です。
ただし、すべての画像が「4 つ意味あるクラスター」を持っているわけではありません。
一般的に適切なクラスター数を決定することは難しい問題ですが、今回の場合は「色が十分に異なるかどうか」だけで判定できるため、必要ならば再度クラスタリングを実行します(例: 3 クラスター画像)。
Oklab
もう一つの濁りの原因は、リサイズライブラリが sRGB 色空間で直接処理していることです。
平均化を sRGB のままで行うと以下の問題があります。
- ガンマ補正(非線形)が施されたまま線形演算を行うため、結果が不正確になります。
- 視覚的な色強度も非線形であるため、感覚上は「縦に区切られた色の帯」が生じやすくなります。
この二つを同時に解決するため、Okmain は Oklab 色空間で計算します。
Oklab で平均化した結果は、sRGB に比べて濁りが少なく、色の混合が滑らかになります。
図では左上が sRGB で混合し、右下が Oklab で混合した例です。
sRGB の方は緑+黄・青+オレンジ領域に濁った茶色が多く見えます。
Oklab を使うことで「見た目の良い主要色」が得られやすくなります。
クラスタソート
Oklab でクラスタリングした後、どのクラスタが「視覚的に優勢」かを決定する必要があります。
ユーザーは単に 4 色ではなく、「もっとも目立つ色」を知りたいと考えます。
Okmain は以下の三つのヒューリスティックでクラスタの優先度を評価します。
- ピクセル数(クラスタ内のピクセル数)
- 中心性(画像中央に近いほど重要)
- 色自体の視覚的優勢(クロマ=彩度)
前二つは「重み付きピクセル数」としてまとめ、画像中央から遠いピクセルは低減します。
例として、背景が薄い灰色である場合でも、前景の緑がより重要と判断されます。
最後に、Oklab のクロマ(彩度)を優勢度の指標として加味し、最も「目立つ」クラスタを上位に並べます。
スウォッチは「最も重要な色」がトップになるようにソートされています(下図参照)。
パフォーマンス
Okmain は「見た目が良い色」を返すだけでなく、高速 であることも重視しました。
- 画像のダウンサンプリング
- 2 のべき乗で縮小し、ピクセル数を 250,000 以下に抑えます。
- Oklab で平均化することでノイズ(見えない色)も除去できます。
- データ構造の最適化
- RGB 配列から L・a・b の配列へ分離し、SIMD ベクトル演算が容易になります。
- 固定数(4 クラスター)が SIMD レジスタに収まるため、パフォーマンスが向上します。
Rust は「正しい浮動小数点計算」をデフォルトで要求するため、自動ベクトル化は難航しますが、SSE2 から AVX2 への切り替えを
target_feature_dispatch で行えばさらに高速化できます。
- 平均実装
- 初期に mini‑batch k‑means を試しましたが、サンプリングステップのオーバーヘッドが大きく、全データセットを走査する方が速いことが判明。
- K‑means++ の初期化はコストがあるものの、安定した結果を得られるため採用しています。
結論として、数百メガピクセル級の画像から主要色を抽出するのに 約 100 ms 程度で処理できます。
LLM を使った試行
プロジェクトの開発過程で「LLM エージェント」がどれほど有用か興味が湧きました。
小規模で明確な課題、既存データ(k‑means は人気アルゴリズム)を前提に、Opus (4.5/4.6) と sprites.dev を組み合わせて自律開発を試みました。
- 結果:最初のバージョンは迅速に完成しましたが、いくつか微妙な誤りや可読性の低さが残っていました。
- Opus は「auto‑vectorisation」に関して不正確な提案をすることが多く、意図的な抽象化をうまく表現できませんでした。
- それでも、デバッグ用バイナリを自律的に生成・確認する段階では時間短縮につながりました。
一方で、sprites.dev の安定性は課題で、数日ごとに遅延や接続不能が発生しました。今後の改善が期待されます。
まとめ
- Okmain は「画像の主要色」を効果的に抽出し、見た目もよい単色を生成します。
- Oklab を利用した平均化とクラスタリング+ソートで、従来手法よりも鮮明な結果が得られます。
- パフォーマンス面では 1×1 リサイズに匹敵する速さを実現しています。
今すぐ Okmain を使ってみてください!
PS. Apple London のマネージャーの方はいらっしゃるなら、ぜひお話ししたいです。
追加情報
- サンプリングだけでは不十分
- 画像ピクセルをランダムにサンプリングして平均化する手法は簡単ですが、ノイズ(例:油絵の乾燥ひび割れ)が過度に反映されます。
- K‑means はクラスタ内で平均化するため、ノイズが独自クラスターとして扱われず、結果を汚すことが少なくなります。