SSIMがウソをつく例

画像の視覚的な差分量を計算する手段としてSSIMはとても重宝していますが、視覚的な差違と乖離するケースを見つけたので紹介します。

# 元画像

横幅1920pxの淡いグラデーションのPNG画像です。ユニークな色数は81,121です。
<a href="https://qiita-image-store.s3.amazonaws.com/0/35178/ae8e4cda-92d7-2ef0-b63f-3911ead6176a.png"><img src="https://qiita-image-store.s3.amazonaws.com/0/35178/ae8e4cda-92d7-2ef0-b63f-3911ead6176a.png" width="480px"></a>
この画像を二種類の方法でPNG8(256色)に減色します。

# 変換A: pngquantで変換

Lossy PNGで精度に定評のある[pngquant](https://pngquant.org/)でPNG8に変換すると以下の通りです。

さすがpngquant。ぱっと見わからないディザリングで256色に減色されています。
<a href="https://qiita-image-store.s3.amazonaws.com/0/35178/1737ff3e-386d-33b1-b710-bedf0b6050b7.png"><img src="https://qiita-image-store.s3.amazonaws.com/0/35178/1737ff3e-386d-33b1-b710-bedf0b6050b7.png" width="480px"></a>

# 変換B: ImageMagickで無造作に変換

`convert`コマンドで以下のように無造作にPNG8に変換します。

```bash
$ convert origina.png png8:8bit.png
```

<a href="https://qiita-image-store.s3.amazonaws.com/0/35178/e46e9d9e-406c-1b54-88da-a65ae118bc98.png"><img src="https://qiita-image-store.s3.amazonaws.com/0/35178/e46e9d9e-406c-1b54-88da-a65ae118bc98.png" width="480px"></a>

見た目の質という点では残念な結果です。

# SSIMを比較

SSIM値を比べてみると、意外な結果が出ました。意外すぎていくつかのツールで算出してみました。

|変換|エンコーダ|元画像|変換画像|ImageMagick|ffmpeg|pyssim|NPM img-ssim|
|---|--------|-----|---|----------:|-----:|-----:|-----------:|
|A|pnqguant|<img src="https://qiita-image-store.s3.amazonaws.com/0/35178/ae8e4cda-92d7-2ef0-b63f-3911ead6176a.png" width="120px">|<img src="https://qiita-image-store.s3.amazonaws.com/0/35178/ae8e4cda-92d7-2ef0-b63f-3911ead6176a.png" width="120px">|0.716548|0.711903|0.8328862|0.8049537035007859|
|**B**|ImageMagick|<img src="https://qiita-image-store.s3.amazonaws.com/0/35178/ae8e4cda-92d7-2ef0-b63f-3911ead6176a.png" width="120px">|<img src="https://qiita-image-store.s3.amazonaws.com/0/35178/e46e9d9e-406c-1b54-88da-a65ae118bc98.png" width="120px">|**0.959803**|**0.950992**|**0.970968**|**0.9684693612331049**|

SSIMはよく「0.95以上で元画像と区別が付きにくい」と言われます。まさかの「B画像の方が似ていて、更に見分けが付きにくい水準」という結果になりました。

# PSNRはどうか

試しに元画像との差をPSNRを求めてみました。PSNRは数値が大きいほど類似している指標です。

この画像の場合は、SSIMより視覚的な違いを言い当てています。

|変換|エンコーダ|元画像|変換後|ImageMagick|ffmpeg|
|---|--------|----|------|----------:|-----:|
|A|pnqguant|<img src="https://qiita-image-store.s3.amazonaws.com/0/35178/ae8e4cda-92d7-2ef0-b63f-3911ead6176a.png" width="120px">|<img src="https://qiita-image-store.s3.amazonaws.com/0/35178/ae8e4cda-92d7-2ef0-b63f-3911ead6176a.png" width="120px">|**32.613**|**32.552913**|
|**B**|ImageMagick|<img src="https://qiita-image-store.s3.amazonaws.com/0/35178/ae8e4cda-92d7-2ef0-b63f-3911ead6176a.png" width="120px">|<img src="https://qiita-image-store.s3.amazonaws.com/0/35178/e46e9d9e-406c-1b54-88da-a65ae118bc98.png" width="120px">|25.8592|25.863008|

# 考察

特徴量は統計的な数値であり、当然ながら万能ではなく向き不向きがあります。

SSIMは輝度・コントラスト・構造を元に類似度を数値化するということで、色相は軽視されているのかもしれません。

変換BのSSIM値が絶対的に高かったのは、輝度やコントラストには色相ほどの変化がなかったのではないかと推測します。

もうひとつ、変換AのSSIM値が相対的に低い数値となったのは、ディザリングの処理が逆に周囲のピクゼルとの輝度やコントラストを大きく変化させたからと推測します。

ディザリングは限られた色数を巧妙に、言わばノイズ状に配置して遠目の近似色を表現する手法なので、SSIMからするとノイズが増えたように見えるということではないでしょうか。

# 2018/10/5 追記と考察その2

[こちらの記事](https://qiita.com/yoya/items/510043d836c9f2f0fe2f#_reference-ba13c8c7bef00f10118b)で取り上げていただきました。

ディザリングは限られた色数の空間的な分布で中間色を表現する印刷的な手法なので、画素として見るとノイズの増加に他ならないのかなぁと思いました。

では色の三原色ということでCMYKに変換してSSIMを計算したらどうなるだろう？と思って試してみました。

## pngquant

```bash
$ compare -metric SSIM -colorspace CMYK -verbose samples/c.png pngquant/c.png NULL:
samples/c.png PNG 1920x1570 1920x1570+0+0 8-bit sRGB 791793B 0.100u 0:00.099
pngquant/c.png PNG 1920x1570 1920x1570+0+0 8-bit sRGB 256c 741833B 0.080u 0:00.079
Image: samples/c.png
  Channel distortion: SSIM
    cyan: 0.737768
    magenta: 0.702178
    yellow: 0.691701
    black: 0.731921
    all: 0.715892
samples/c.png=> PNG 1920x1570 1920x1570+0+0 8-bit CMYK 6.750u 0:06.750
```

## ImageMagick

```bash
$ compare -metric SSIM -colorspace CMYK -verbose samples/c.png png8/c.png NULL:
samples/c.png PNG 1920x1570 1920x1570+0+0 8-bit sRGB 791793B 0.110u 0:00.120
png8/c.png PNG 1920x1570 1920x1570+0+0 8-bit sRGB 121c 58251B 0.060u 0:00.059
Image: samples/c.png
  Channel distortion: SSIM
    cyan: 0.836699
    magenta: 0.816028
    yellow: 0.866341
    black: 0.509111
    all: 0.757045
samples/c.png=> PNG 1920x1570 1920x1570+0+0 8-bit CMYK 6.980u 0:07.069
```

全体としてはディザリングの方が低評価ですが、`black`のSSIMはなんだかしっくり来る感じです。偶然かもしれませんが。