【SSIM】画像評価指標を使って画質の劣化がわからないギリギリまでクラウドの容量を削減してみる。カメラ内の画質設定も

Tips

こんにちは、Nanasです。

前回記事にもしたGoogleフォトを相変わらず愛用していて、2021/6あたりから容量無制限がなくなって容量不足に怯えながら使用しているわけですが、流石に圧縮を考え始めねばということで今回ちょっと頭を使って考えてみました

4年以上残ってるじゃねんだよな、4年ちょいしか残ってないんだよ
俺の人生あと何年あると思ってんだ

圧縮の理由、目標、条件等色々

基本的に画像や動画を PC、Googleフォト、Amazon Photos で3重バックアップを取っています
なぜクラウドが2種もあるかというと
Googleフォトは閲覧性が神だが容量制限アリAmazon Photosは閲覧性クソだが容量無制限
と一長一短なので併用してその欠点を補完しあっているからです

とくにGoogleフォトの閲覧性は代えがたいもので重宝しているんですが、割と重大な欠点があって
容量節約設定だと解像度が16MPまで縮小される んですよね
容量節約や通信の軽量化の点からも圧縮は全然大歓迎な上に、基本的にスマホで撮影、生成したデータは16MP以上のものはほぼないので全然問題なかったんですよね、以前は

カメラをやるようになって急に撮影枚数が増えた上にしっかり16MP以上の解像度なので縮小されてしまうんですよね~これが
流石にカメラで普段「解像解像解像解像!」とか言ってるのに解像度を落とされるのは気に食わないのでそれをどうにかしようと言うのが今回の記事です

解像度が下げられてしまった写真(本来は26MP)

今まではweb版からD&Dでjepgを投げると解像度を維持できたんですけどいかんせんオリジナルでのアップロードになるので一眼で撮ったjpegだと平気で8MB/枚とかになって馬鹿にならないんですよね

今回は一眼(α7RⅢ、α6300)で撮影したjpegデータを

  • 解像度をオリジナル(RⅢは42.4MP/7952 x 5304、6300は24MP/6000×4000)
    から下げることなく
  • ある程度拡大しても画質の違いがほぼわからない程度に
  • Exifなどのメタデータはすべて維持したまま

圧縮すること、またその設定のスイートスポットを見つけることが目標です

また、撮影時に両機種ともRAW+JPEGで保存をしており、RAWはローカルなりAmazon Photosなりにブン投げているのであくまでGoogleフォトに上げる jpegデータはサムネ的な軽量で扱いやすいもの、不可逆圧縮も一切躊躇しないものとして扱います

やっぱり、写真保存庫としてはローカルやAmazon Photosは非常に優秀なんだけど写真閲覧ツールとしてはGoogleフォトの右に出る者はいない気がする
検索機能が優秀すぎるし、人物や物体認識、思い出機能(たまに月日の経過で脳を破壊する)があるのが単なるクラウドの域を超えていて素晴らしい。

先にいうと圧縮自体はGUIで死ぬほど簡単なんだけど、その圧縮率の設定を見つけるためにSSIMという画像処理では有名な指標を用いるわけです。
今回の記事は解析と考察がメインなのでまあ圧縮のやり方については超適当です。

とりあえず圧縮

使うソフトは caesium-image-compressor

圧縮先の形式はWebPが一番圧縮率が高いのはわかっているんですが、クラウドで手軽に扱うことや互換性などを考えてjpegにします

可逆圧縮、不可逆圧縮両方できるのですが(jpegに可逆あったんすね)
可逆圧縮→不可逆圧縮 や 不可逆圧縮→可逆圧縮 のように2回圧縮をかけたらさらに効率化ができるのではないかと考えていたけど、不可逆圧縮1回でも大して圧縮率に差がなかった

なんか知らないけど最終的なファイルサイズはほぼ同じところに収束するんだよね、面白いけど何故か理解するまでは頭が追いついていない

そのため圧縮は1回、JPEGの品質レベルを変化させ、今回は80~90の11段階で圧縮をしました
α6300で撮影した約200枚ほどをサンプルにやってみました

ちなみにExifなどのメタデータはすべて引き継がれていてGoogleフォトにアップしても時系列が狂ったりなどはしませんでした。

では次のステップ、今回の本題、SSIMです

SSIMによる画質評価

SSIMってなに?

超~~~~~~ざっくりいうと、「パッと見の画像の類似度」

PSNRとという有名な指標もあるのですが、こちらは1画素ごとの厳密な評価をするので
例えば全く同じ配列で上下左右に数pxズレているともう別画像として認識されます

一方SSIMは画像の構造的な類似度を評価するので多少ズレていたりとか色が数px違っていてもいいのです、この構造的にというのが噛み砕いて言うとパッと見というわけ

機械的な指標に比べてより人間の感覚に近いということで注目されているんですね

ここで覚えておいてほしいのが
1.00が最大値(全く一緒)で0.95を超えたあたりから違いがほぼわからない ということ

LPIPSという深層学習を元にした更に人間の感覚に近い指標もでてきてるんだけどこれはちょっと計測の仕方が分からなかったのでスルーしました… また気が向いたらやります(n年後

早速計測

SSIMは元画像と処理後の画像、2つの画像を読み込ませることで計算できます

今回はPythonで記述しました、ネットを漁っていたらちょうどよく簡単に書けてしかもなんとGPU処理までしてくれてしまう超有能なコードの紹介がされているところがあったのでありがたく使わせていただきました。

大学でMatlabという学術計算に特化した言語をちょうど学んでいて、これはプラグイン等無しでデフォでSSIMの計算ができるほど向いている言語なのですがいかんせん解析する画像が42だの24MPの高画素でCPUオンリーの処理だとエラーを吐きまくるので断念。

from SSIM_PIL import compare_ssim
from PIL import Image
import time
from statistics import mean
import statistics

# 連番の最初と最後を指定
first = "連番の最初の番号"
last = "連番の最後の番号"

# 配列"SSIM"を初期化、処理時間の計測開始
SSIM = []
print("SSIMの計算を開始します...")
time.sleep(0.150)
start = time.time()

for num in range(first,last+1):

    image1 = Image.open("元画像のパス")
    image2 = Image.open("比較する画像のパス")

    # 画像の構造的類似度をOpenCLで計算 (Compare images using OpenCL by default)
    value = compare_ssim(image1, image2)
    SSIM.append(value)
    print(f"SSIM_{num} =   {value}")

    # GPUが使えないときはコメントアウト解除して
    #  Compare images using CPU-only version
    # value = compare_ssim(image1, image2, GPU=False)
    # print(f"SSIM_{num} =   {value}")

end = time.time()
time.sleep(0.250)
process_time = end - start
avgSSIM = mean(SSIM)
medSSIM = statistics.median(SSIM)
maxSSIM = max(SSIM)
minSSIM = min(SSIM)
print("\n")
print(f"SSIMの平均値:{avgSSIM}")
print(f"SSIMの中央値:{medSSIM}")
print(f"SSIMの最大値:{maxSSIM}")
print(f"SSIMの最小値:{minSSIM}")
print(f"処理時間:{process_time}秒")
print("\n")


解析に使ったコードを適当に他の人の環境でも使える感じに書き直してみてみたけど全く動く気がしないので真似したい人はさっきのサイトとこれ参考に適当にやってください
たぶん一番上の statistic の import ができてないとかが注意

さっき圧縮したサンプル(品質レベル80-90)のSSIMを解析し、圧縮率などをまとめたものが以下になります

SSIM
Sheet1 平均値,中央値,最大値,最小値,圧縮率,圧縮前,圧縮後,サイズの差,SSIM/サイズ,画質差 80,0.9745,0.9754,0.9830,0.9369,0.796,807.38,164.92,4.7708 81,0.9748,0.9757,0.9831,0.9390,0.792,807.38,168...

オリジナルのファイルを上においておきます

  • SSIMは0.95を超えると感覚的な差異がわからなくなる(最小値が0.95以上を選ぶ)
  • 品質レベルを1増やしたときのファイルサイズの差が大きいところを間引く(効率が悪いため)
  • 品質レベルの数値が低いほど基本的にファイルサイズあたりの画質は良い

この3点を考慮すると品質レベル Q=85 が最適解

91以上も解析しようか迷いましたが正直ファイルサイズの跳ね上がり方が現実的ではなかったので今回はここまでにしました

品質レベルは決まった、そのあとは?

上の検証で品質レベル85が画質を維持しつつ最もファイルサイズを削減できる設定であることがわかった
しかしこれは撮影後にバックアップ前にPCで行う処理の最適解を求めたに過ぎない

ふと カメラ側の画質設定も見直したほうが良くない? と思った

SONYのカメラはJPEG画質を複数段階に変更でき、俺の所持しているα7RⅢ、6300では

X.FINE エクストラファイン、FINE ファイン、STD、スタンダード

の3段階で変更できる
おそらくJPEG画質の差だろうと思ったのでちょっと調べてみると

こんな感じになっていた。(ちょっと打つのめんどくなってきたのでツイッターを転載

詳しいことはスレッドを読んでもらうとして、
100、95、90の画質設定になっており、スタンダードなんて名前をしているくせに普通に低圧縮高画質設定になっている。

ほぼ同条件で撮影した写真3枚が以下のようになる
① X.FINE Q=100 16.5MB
② FINE Q=95 7.78MB
③ STANDARD Q=90 4.81MB
①と②、③を比較するとSSIMが両方とも0.987程度なのでファイルサイズに対して画質があまり変わらないため、スタンダードで十分

しかし面白いのが、カメラ内で圧縮された画像をPCで画質85で再圧縮すると
① 1.41MB SSIM=0.987
② 1.47MB SSIM=0.981
③ 1.71MB SSIM=0.980
となり最終的なファイルサイズがほぼ変わらないどころか
エクストラファインが一番ファイルサイズが小さく、SSIMが高くなったしまった

ここまで来るとカメラ側の設定はエクストラファインでいいのでは?と思うかもしれない
確かにクラウドに最終的にアップロードされる段階まで行けばそれでいいかもしれないが、それまでのことも考えなければならない

クラウド保存前にもデータのやり取りは行われる、例えば撮影時のSDカードへの書き込みや、外出先でのWi-Fi転送だ
その間の転送時間を考えるととりあえず、エクストラファインは論外。ついでファインとスタンダードだがどちらが有用かを少し検証してみる

RAWデータからAdobe Lightroom Classicを用いてファイン、スタンダード相当の品質95、90のJpegファイルを生成、そこからさらに先程のソフトで品質85で圧縮をかける
サンプルはα7RⅢで撮影した42MPの画像30枚

←ファイン相当 スタンダード相当→

結果は以上の通り
圧縮後のファイルサイズがやはりほぼ一緒になった、先程の検証は偏っていただけであったことがわかった。

とここで面白いことに気づいたのでまとめてみた

カメラで生成されたJpegとPCで再圧縮したJpegを比べるとSSIMは0.973なのに対して
RAWデータから生成したQ=100のマスター画像と再圧縮後の画像を比べると、なんとSSIM=0.997とかなり高い値が算出されたことがわかる

ここからは憶測だが、ノイズが乗った画像同士を比べると類似度はある程度で頭打ちになるが、ノイズレス(極小)の画像と処理後の画像は実はかなり類似している。ということではないか

…といろいろ書いたがカメラ内の画質設定はファインとスタンダードどちらでも対して変わらない
データハンドリングを考えて今回は スタンダード を選ぶ

まとめ

かなり長丁場の記事で自分でも途中で色々訳解んなくなってきたのでここで最後に結論を

圧縮時のJPEG品質レベルは Q=85
カメラ内のJPEG画質は STDスタンダード Q=90

これでファイルサイズを60~70%程度削減できるためぜひみんなも真似してほしい

以下、雑記
解析などをしてみた感想ですが、JPEGは品質レベル85が最適解というのはGoogleから結構言われていることでありまあ従っとけばいいかなとか思ってたんですけど、実際にSSIMという指標を使ってそれを実証できたのでかなり満足しました。Pythonの練習にもなりましたし画像圧縮に関する新しい知識も色々ついたのでやっぱ画像処理っておもしれえなって思いました。
先の赤文字の結論意外は結構ガバガバな感じなので間違ってるところとかあるかもしれないけどお目に見てください、まじで自分でも途中で何について書いているかわからなくなってきた()

SNSでのシェアと、もしよかったら他の記事も見て行ってください〜

ではまた次回!!

参考

SSIM-PIL
Comparison of two images using the structural similarity algorithm (SSIM).

コメント

タイトルとURLをコピーしました