ヒストグラムマッチングによる色調統一 - 複数画像の色合わせ技術
ヒストグラムマッチングとは - 画像間の色調を揃える技術
ヒストグラムマッチング (Histogram Matching / Histogram Specification) は、ある画像のヒストグラム (輝度分布) を、目標となる別の画像のヒストグラムに一致させる変換技術です。これにより、異なる条件で撮影された複数の画像の色調を統一したり、特定の雰囲気を持つ画像の色調を別の画像に転写したりできます。
ヒストグラム均一化との違い:
ヒストグラム均一化 (Histogram Equalization) は、ヒストグラムを一様分布に変換してコントラストを最大化する手法です。一方、ヒストグラムマッチングは任意の目標分布に変換できる汎用的な手法です。均一化は目標分布が一様分布に固定されたマッチングの特殊ケースと見なせます。
応用場面:
- 映像制作: 異なるカメラやレンズで撮影したショット間の色調統一
- パノラマ合成: 隣接画像間の明るさ・色調の差を解消
- 衛星画像: 異なる時期に撮影された画像の比較分析
- 医療画像: 異なる装置で撮影された画像の標準化
- スタイル転写: 参照画像の色調を別の画像に適用
基本的な考え方:
ヒストグラムマッチングは、入力画像の各ピクセル値を、出力画像で目標ヒストグラムが実現されるように変換する写像 (ルックアップテーブル) を構築します。この写像は累積分布関数 (CDF) を介して計算されます。入力の CDF と目標の CDF を対応付けることで、任意の分布変換が実現できます。
CDF ベースの変換アルゴリズム
ヒストグラムマッチングの核心は、累積分布関数 (CDF: Cumulative Distribution Function) を利用した変換です。入力画像と目標画像の CDF を計算し、両者を対応付けることで変換関数を導出します。
アルゴリズムの手順:
1. 入力画像のヒストグラム H_src と CDF_src を計算します。2. 目標画像のヒストグラム H_ref と CDF_ref を計算します。3. 各入力値 s に対し、CDF_src(s) に最も近い CDF_ref(t) を持つ値 t を見つけます。4. 変換テーブル T[s] = t を構築します。5. 入力画像の各ピクセルに変換テーブルを適用します。
数学的な導出:
入力画像のピクセル値 s の CDF を C_s(s)、目標の CDF を C_r(r) とします。変換関数 T は T(s) = C_r^(-1)(C_s(s)) で定義されます。離散的な場合、C_r の逆関数は「C_r(r) >= C_s(s) を満たす最小の r」として近似的に計算されます。この操作は O(256) のルックアップテーブルとして事前計算でき、画像サイズに依存しない高速な変換が可能です。
グレースケール画像での実装:
8 ビットグレースケール画像の場合、ヒストグラムは 256 ビンで計算されます。CDF は ヒストグラムの累積和を総ピクセル数で正規化したものです。NumPy では cdf = np.cumsum(hist) / np.sum(hist) で計算できます。変換テーブルの構築は np.searchsorted(cdf_ref, cdf_src) で効率的に実行できます。
カラー画像への拡張:
カラー画像では、R, G, B 各チャネルに独立にヒストグラムマッチングを適用する方法が最も単純です。ただし、チャネル間の相関が無視されるため、色相のシフトが発生することがあります。より高品質な結果を得るには、Lab 色空間に変換し、L (明度) チャネルにマッチングを適用する方法や、3D ヒストグラムを使用する方法があります。
多チャネル・多次元ヒストグラムマッチング
RGB チャネルを独立に処理する単純な手法では、チャネル間の相関が失われ、不自然な色が生じることがあります。より高度な手法では、色空間全体を考慮した多次元マッチングを行います。
Lab 色空間でのマッチング:
Lab 色空間は人間の知覚に基づいており、L (明度)、a (緑-赤)、b (青-黄) の 3 チャネルが比較的独立しています。Lab 空間で各チャネルに独立にマッチングを適用すると、RGB 空間での処理より自然な結果が得られることが多いです。特に明度の変換が色相に影響しにくい点が利点です。
Optimal Transport (最適輸送) によるマッチング:
最適輸送理論に基づく手法は、入力の色分布を目標の色分布に変換する最適な写像を求めます。Wasserstein 距離を最小化する輸送計画を計算し、各ピクセルの色を最適に変換します。計算コストは高いですが、チャネル間の相関を完全に保持した高品質な色変換が可能です。Python の POT (Python Optimal Transport) ライブラリで実装できます。
Reinhard の色転写法:
Reinhard ら (2001) が提案した手法は、Lab 色空間で各チャネルの平均と標準偏差を一致させる簡易的な色転写です。t = (s - μ_src) × (σ_ref / σ_src) + μ_ref の線形変換で、計算が極めて高速です。ヒストグラムの形状は変えずに、全体的な色調 (明るさ、彩度) を転写するのに適しています。
ニューラルネットワークベースの手法:
深層学習を用いた色転写手法も発展しています。ヒストグラムマッチングの限界 (空間的な対応を考慮しない) を克服し、セマンティックな対応関係 (空と空、肌と肌) を考慮した色転写が可能です。ただし、計算コストが高く、学習データが必要な点がトレードオフです。
映像制作でのカラーマッチング実践
映像制作では、異なるカメラ、レンズ、照明条件で撮影されたショットの色調を統一する「カラーマッチング」が不可欠です。ヒストグラムマッチングはその基盤技術の一つです。
ショット間の色調統一:
同じシーンを複数のカメラで撮影した場合、カメラのセンサー特性やホワイトバランス設定の違いにより色調が異なります。基準となるショット (リファレンス) を選び、他のショットのヒストグラムをリファレンスに合わせることで、編集時のカット切り替えが自然になります。
DaVinci Resolve でのワークフロー:
プロの映像編集ソフト DaVinci Resolve には、ショットマッチング機能が搭載されています。リファレンスクリップを指定し、自動的に色調を合わせる機能です。内部的にはヒストグラムマッチングに加え、肌色検出やハイライト・シャドウの個別調整が行われています。手動での微調整も可能で、カラーホイールやカーブで追加補正を行います。
時間方向の一貫性:
動画にヒストグラムマッチングを適用する場合、フレーム間の一貫性が重要です。各フレームを独立に処理すると、フレーム間で色調がちらつくことがあります。対策として、時間方向のフィルタリング (前後フレームの CDF を平均化) や、キーフレームベースの補間 (特定フレームでマッチングを計算し、中間フレームは補間) が使用されます。
HDR 映像での注意点:
HDR (High Dynamic Range) 映像では、通常の 8 ビットヒストグラムでは不十分です。10 ビットや 12 ビットの精度でヒストグラムを計算し、PQ (Perceptual Quantizer) や HLG (Hybrid Log-Gamma) の伝達関数を考慮した変換が必要です。トーンマッピングとの組み合わせも重要で、HDR から SDR への変換時にヒストグラムマッチングを活用することがあります。
パノラマ合成と衛星画像での色調補正
パノラマ合成や衛星画像解析では、隣接する画像間の色調差を解消するためにヒストグラムマッチングが活用されます。撮影条件の違いによる色調差を補正し、シームレスな合成を実現します。
パノラマ合成での色調統一:
パノラマ撮影では、カメラの向きが変わることで露出や色温度が変化します。空に向けたショットは明るく、地面に向けたショットは暗くなります。隣接画像の重複領域でヒストグラムマッチングを適用し、接合部での色調差を最小化します。重複領域のみを参照することで、各画像の特性を保持しつつ接合部を滑らかにします。
ゲインコンペンセーション:
パノラマ合成では、ヒストグラムマッチングの代わりにゲインコンペンセーション (露出補正) が使用されることもあります。各画像にスカラーのゲイン値を乗算し、重複領域での輝度差を最小化します。ヒストグラムマッチングより単純ですが、全体的な明るさの差を効率的に補正できます。OpenCV の cv2.detail.ExposureCompensator がこの機能を提供しています。
衛星画像の時系列解析:
衛星画像では、撮影時期による太陽高度の違い、大気条件の変化、センサーの経年劣化などにより、同じ地域でも画像の色調が大きく異なります。時系列比較 (変化検出) を行う前に、ヒストグラムマッチングで画像間の放射量を正規化します。基準画像を選定し、他の時期の画像をマッチングすることで、真の地表変化のみを検出できます。
マルチソース画像の統合:
異なるセンサー (Landsat、Sentinel-2、SPOT など) で撮影された衛星画像を統合する際にも、ヒストグラムマッチングが使用されます。センサーごとの分光応答特性の違いを補正し、一貫したデータセットを構築します。ただし、物理的に異なるバンド構成を持つセンサー間では、単純なヒストグラムマッチングでは不十分で、相互校正 (Cross-Calibration) が必要になることがあります。
実装ガイド - Python でのヒストグラムマッチング
Python を使用したヒストグラムマッチングの実装を、基本的な手法から高度な手法まで段階的に解説します。scikit-image、OpenCV、NumPy を活用した実践的なコードを紹介します。
scikit-image による実装:
scikit-image は exposure.match_histograms() 関数を提供しており、最も簡単にヒストグラムマッチングを実行できます。from skimage.exposure import match_histograms; matched = match_histograms(source, reference, channel_axis=-1) の 1 行で、カラー画像のチャネルごとのマッチングが完了します。内部的には CDF ベースの変換が実装されています。
NumPy による手動実装:
学習目的や細かい制御が必要な場合、NumPy で手動実装します。hist_src, _ = np.histogram(src, bins=256, range=(0, 255)) でヒストグラムを計算し、cdf_src = np.cumsum(hist_src).astype(float) / src.size で CDF を求めます。変換テーブルは lut = np.searchsorted(cdf_ref, cdf_src).astype(np.uint8) で構築し、matched = lut[src] で適用します。
部分領域でのマッチング:
画像全体ではなく、特定の領域 (ROI) のヒストグラムを基準にマッチングすることも可能です。例えば、空の領域のみを参照して空の色調を統一したり、肌色領域を基準にポートレートの色調を合わせたりできます。マスク画像を使用して ROI を指定し、その領域のヒストグラムのみを計算します。
バッチ処理と動画への適用:
複数画像のバッチ処理では、リファレンス画像を 1 枚選定し、全画像をそのリファレンスにマッチングします。動画の場合は、最初のフレームまたは代表フレームをリファレンスとし、全フレームに適用します。フレーム間のちらつきを防ぐため、CDF の時間方向平滑化 (指数移動平均) を適用することが推奨されます。処理速度は 1080p 画像で 1 フレームあたり 5-10ms 程度で、リアルタイム処理が十分可能です。