低照度画像補正を「暗い画像を明るくする処理」としてだけ見ず、明るさと色の比率を分けることで何が変わるのかを、ガンマ補正・CLAHE・Retinex・ICDNetで比較します。

参考にしたもの

  • Rethinking Low-Light Image Enhancement: A Log-Domain Intensity--Chromaticity Decoupling Perspective arXiv:2605.02627。低照度画像補正をRGB-to-RGBの直接変換としてではなく、log-domainのIntensityとChromaticityに分けて扱う論文です。 https://arxiv.org/html/2605.02627v1

  • mubaisam/ICD 上記論文のICDNet実装リポジトリです。test.py による直接推論、eval.py によるPSNR/SSIM/LPIPS評価、checkpoint指定などがREADMEで説明されています。 https://github.com/mubaisam/ICD

  • 今回使った比較notebook この記事の図と簡易指標を作るために使ったコードです。 low_light_icd_comparison_notebook.ipynb

  • Pexels: Black Metal Window Frame 今回の比較に使った低照度画像です。暗い階段室と明るい窓が同時に写っており、暗部補正・白飛び・色の安定性を比較しやすい画像でした。写真作者はEkaterina Astakhovaです。 https://www.pexels.com/photo/black-metal-window-frame-3185041/

  • Pexels License https://www.pexels.com/license/

Contents

  • 結論
  • まず、低照度補正は何が難しいのか
  • 今回比較する方法
  • 実験に使った画像
  • 結果1:まず全体を比べる
  • 結果2:暗部を拡大して比べる
  • 結果3:IntensityとChromaticityを可視化する
  • 結果4:公式ICDNetも含めて比べる
  • 簡易指標で見る
  • この結果から分かったこと
  • 注意点
  • まとめ

結論

低照度画像補正は、単に暗い画像を明るくする処理ではありません。 一般的な補正方法を使用するだけでは画像は明るくなりますが、同時に色飛びやノイズが目立つようになります。

今回の紹介しようと思っているICDNetは、画像全体をかなり明るくしつつ、Retinexほど極端には白く飛ばさず、手すりや階段の暗部も見えるようにしていました。 ただし、窓周辺にはわずかな色の変化も見えるため、万能というより「明るさ回復と色の安定性のバランスを取りにいく方法」といえるように思いました。

この記事で一番伝えたいことは、こちらです。

暗い画像をただ明るくすると、色とノイズが目立つようになります。ICDは、明るさと色の比率を分けることで、その壊れ方を抑えようとする方法です。

まず、低照度補正は何が難しいのか

暗い画像を明るくするだけなら、処理自体は簡単です。

たとえば画素値を大きくしたり、ガンマ補正で暗部を持ち上げたりすれば、画像はすぐ明るくなります。

しかし、低照度画像では暗部の信号そのものが弱いため、ノイズの割合が大きくなります。 そこを無理に明るくすると、被写体だけでなく、暗部ノイズ、色ムラ、RGBチャンネルごとの小さなズレも一緒に目立ちます。 つまり、次のような条件を同時に満たすことが難しいです。

暗い部分は見えるようにしたい
しかしノイズは増やしたくない
しかし色は自然に保ちたい
しかし明るい窓やライトは白飛びさせたくない
しかし細部は残したい

今回読んだICDの論文は、この問題を「もっと強いネットワークでRGB画像を明るいRGB画像に変換する」だけでなく、そもそもRGBのまま直接補正するから、明るさ・色・ノイズが絡まりすぎるのではないかと考えます。

そこで画像を、次の2つに分けます。

Intensity: その画素がどれくらい明るいか
Chromaticity: その明るさの中でRGBがどんな比率か

この分け方によって、低照度補正を、

暗いRGB画像 → 明るいRGB画像

という直接変換ではなく、

明るさを回復する
+
色の比率を安定化する

という問題として扱います。

今回比較する方法

今回のnotebookでは、次の方法を比較しました。

方法役割今回の位置づけ
input元画像暗い画像としての例
gammaガンマ補正 + gainただ明るくする代表例として
CLAHELabのLチャンネルに局所ヒストグラム補正局所コントラストを上げる代表例
RetinexMulti-Scale Retinexの簡易実装照明成分を補正する例
ICD-inspiredIntensity/Chromaticity分解の簡易実装論文の発想を可視化する説明用
official ICD公式ICDNet論文モデルの実装を使った推論

ここで注意したいのは、ICD-inspired は論文の完全再現ではないことです。

これは、

Intensity = max(R, G, B)
Chromaticity = log(RGB / Intensity)

という分解の考え方を、記事で見せるための簡易実装です。論文モデルそのものではありません。論文モデルとしての比較は、後半の official ICD で見ています。

実験に使った画像

今回は、Pexelsの Black Metal Window Frame を使いました。 暗い階段室の中に明るい窓があり、左側や手すり周辺はかなり暗く、右側の壁と窓は明るいという構図です。

この画像で、このような観点で低照度補正の比較を行いました。

暗部を持ち上げられるか
窓を白飛びさせないか
壁や手すりの色が不自然にならないか
暗部のノイズや色ムラが目立たないか

結果1:画像全体での比較

図1. input / gamma / CLAHE / Retinex / ICD-inspired の比較

gamma は、元画像よりかなり見えるようになります。 左側の暗い壁や階段の輪郭もくっきりとしています。 ただし、全体が灰色がかった印象になり、窓周辺は白飛び気味です。 単純に明るくするだけでは不要な箇所も明るくなってしまうのでこのようになっていそうです。

CLAHE は、今回の設定では控えめな補正になっています。 元画像より局所的な差は少し出ていますが、画像全体を大きく明るくするというより、暗さを残したまま局所コントラストを上げた結果になっています。 暗い雰囲気は保たれていますが、「低照度画像を見やすくする」という意味では少し弱くもう少し補正したいです。

Retinex は一番大きく変化しました。壁、手すり、階段が一気に見えるようになります。 しかし、全体が白っぽく、淡く、やや不自然な結果です。 特に壁面や手すりの周辺に、色の薄さや局所的な違和感が出ています。 これは「見えるようにする」力は強い一方で、「不自然」に見えてしまっている例です。

ICD-inspired は、かなり CLAHE と似た結果になっています。 窓周辺の明るさは保ちつつ、暗部を大きく持ち上げません。 今回の設定では、暗部の色を信用しすぎないようにした結果、左側がかなり黒く残りました。 ※こちらは論文モデルの結果ではなく、分解発想を可視化するための簡易実装です。

結果2:暗い部分を拡大して比べる

図2. 暗部cropの比較

全体画像だけでは、違いが分かりにくいため、暗部をcropして違いを比較してみます。

gamma は、暗い壁は見えやすくなっていますが、窓の明るい部分も一緒に強くなり、全体がやや眠い灰色に寄っています。

CLAHE は、暗い壁を無理に明るくしません。 そのため、自然さは保ちやすいですが、暗部の情報を積極的に見せるには弱いです。

Retinex は、暗部が大きく持ち上がります。 壁の面はかなり見えるようになりますが、明るくなりすぎて、元の暗い空気感はほとんど消えています。 また、壁や手すりの境界に少し不自然な色が出ています。

ICD-inspired は、暗い領域をほぼ暗いままにしています。 これは、暗部のchromaticityを強く信用しない設定にしているためです。 この簡易実装では、色ノイズの増幅は抑えられますが、暗部の視認性は犠牲になっています。

この結果から分かるのは、低照度補正には必ずトレードオフがあるということです。

明るくするほど見える
しかし、ノイズや白飛びや色ズレも出やすい

抑えるほど自然さは保てる
しかし、暗部は見えにくいまま残る

結果3:IntensityとChromaticityを可視化する

図3. 元画像 / Intensity / Chromaticity可視化

次に、ICDの考え方を理解するために、元画像をIntensityとChromaticityに分けて可視化しました。 中央の intensity=max(R,G,B) は、その画素の明るさの包絡を表します。窓や右側の壁は明るく、左側の壁や階段はかなり暗いことが分かります。 右の chromaticity visualization は、RGBの絶対値ではなく、チャンネル間の相対比率を可視化したものです。これはそのまま自然な色として見る画像ではありません。むしろ、画像の中で色比率がどのように変わっているかを見るための図です。

この図が重要なのは、ICDがRGB画像をそのまま見ていないことを直感的に示しているからです。

普通の補正では、暗いRGB値を直接持ち上げます。

暗いRGB値
↓
明るくする
↓
色ズレもノイズも一緒に増えやすい

ICDでは、まず次のように分けます。

RGB
↓
Intensity: 明るさの包絡
Chromaticity: RGB比率

そのうえで、明るさ回復と色補正を別々に扱います。

この発想が、今回の論文の中心です。

結果4:公式ICDNetも含めて比べる

図4. 公式ICDNetを含めた比較

最後に、公式リポジトリのICDNetを使った結果も並べます。

ここで見るべきなのは、ICD-inspiredofficial_icd の違いです。

ICD-inspired は説明用の簡易実装なので、かなり暗部を抑えています。一方、official_icd は学習済みモデルなので、暗部をしっかり持ち上げています。手すり、階段、壁の情報がかなり見えるようになっています。

それでいて、Retinex ほど全体が白く飛んでいるわけではありません。gamma と比べても、単に画像全体を灰色っぽく持ち上げるだけではなく、窓周辺や壁の明るさのバランスを取りながら補正しているように見えます。

ただし、公式ICDNetも完璧ではありません。窓周辺には少し色が乗って見える部分があります。今回の画像だけで判断すれば、

gamma: 素直に明るいが白飛び・灰色化しやすい
Retinex: 強く見えるが過補正に見える
ICD-inspired: 色暴走を抑えるが暗すぎる
official_icd: 明るさと自然さのバランスが良いが、完全に無色・無破綻ではない

という印象です。

簡易指標で見る

今回は正解画像がないため、PSNRやSSIMは計算していません。

代わりに、観察補助として次の簡易指標を出しました。

methodmean_lumadark_10pct_luma_stdmean_saturationclip_white_ratioclip_black_ratio
input0.0920.0060.2080.0000060.000375
gamma0.2710.0270.1230.0308600.000007
clahe0.1230.0100.1500.0000340.000107
retinex0.6890.1810.0720.0139740.009154
icd_inspired0.1120.0000.0620.0107620.195571

mean_luma は平均輝度です。gamma は元画像より大きく上がっています。retinex はさらに大きく上がっており、図で見た「過補正に近い明るさ」と対応しています。

dark_10pct_luma_std は暗部の輝度標準偏差で、暗部のばらつきの代理指標です。これはノイズそのものの厳密な測定ではありませんが、暗部の持ち上がり方の違いを見る補助になります。gammaretinex では値が上がっています。暗部が見えるようになる一方で、暗部のばらつきも大きくなっていると読めます。

clip_white_ratio は白飛びに近い画素の比率です。gamma では 0.030860 と大きめになっています。これは窓周辺が飛びやすくなっている見た目と一致します。

clip_black_ratio は黒つぶれに近い画素の比率です。icd_inspired は 0.195571 とかなり高くなっています。簡易実装が暗部をかなり保守的に扱ったことが、数値にも出ています。

ただし、これらの指標は絶対評価ではありません。正解画像がないため、「どれが正しいか」を決めるものではなく、図を見るための補助です。

この結果から分かったこと

今回の1枚の画像からだけでも、かなり重要なことが分かりました。

1. 「明るい」と「自然」は違う

Retinex は非常に明るくなりました。暗部の見えやすさだけで言えば強いです。

しかし、見た目としては白っぽく、元画像の空気感や階段室の暗さは失われています。

つまり、低照度補正では、平均輝度が高ければよいわけではありません。

2. 単純な明るさ補正は分かりやすいが、白飛びしやすい

gamma はかなり実用的です。処理は簡単で、画像もすぐ見えるようになります。

ただし、今回のように暗い室内と明るい窓が同時にある画像では、窓の白飛びが出やすいです。

これは、画像全体をまとめて明るくする処理の限界です。

3. ICDの価値は「強く明るくすること」ではなく「壊れ方を抑えること」にある

公式ICDNetの結果を見ると、Retinexほど極端に明るくするわけではありません。

しかし、暗部を見えるようにしつつ、全体を極端に白くしすぎない方向に補正しています。

ここが、今回の論文を読むうえで大事なところです。

ICDは、暗い画像をただ明るくする方法ではありません。

明るさを回復する
+
色の比率を安定化する
+
チャンネルの異常な増幅を抑える

という方法です。

まとめ

低照度画像補正は、単に暗い画像を明るくする処理ではありません。

今回の比較では、ガンマ補正、CLAHE、Retinex、ICD-inspired、公式ICDNetを同じ画像に適用しました。

結果として、次のことが見えました。

Gamma:
  明るくしやすいが、白飛びや灰色化が出やすい

CLAHE:
  局所コントラストを出せるが、今回の設定では明るさ回復は控えめ

Retinex:
  強く見えるようになるが、過補正で白っぽくなりやすい

ICD-inspired:
  色比率を抑える発想は見えるが、簡易実装では暗部が残りすぎる

Official ICDNet:
  暗部を持ち上げつつ、Retinexほど全体を壊さないバランス型に見える

この論文の面白さは、低照度補正を「暗いRGBを明るいRGBにする問題」としてだけ見ないところだと感じました。

画像を、

Intensity: 明るさ
Chromaticity: 色の比率

に分けることで、明るさ回復と色補正を分けて扱います。

その結果、暗部を明るくするときに起きやすい色ノイズやチャンネルの暴走を抑えようとします。

最後にもう一度まとめると、この記事の結論はこれです。

暗い画像を明るくするだけでは、色とノイズも一緒に持ち上がります。ICDは、明るさと色の比率を分けることで、低照度補正の壊れ方を抑えようとする方法です。