2022.5.10

画像の明るさをプログラムで分析する

技術

SCROLL DOWN SCROLL DOWN SCROLL DOWN

こんにちは!AIサービス開発室の鈴木です。5月、新緑がまぶしい季節になりましたね。花粉症の私としては、スギやヒノキの花粉の飛来が落ち着いたことも相まって、とても清々しい気分で日々を過ごしています。肝心のAI事業については様々な方にご助言をいただきながら、徐々に企画を具体的なものにしているところです。新しい事業を起こす過程は非常にエキサイティングだと思います。光明が差したかと思えば、急に真っ暗闇になるといった感じで心が落ち着く間がありません。また、深く思考するため学ぶことも多いです。その辺りはいずれこのブログに投稿したいと思います。

さて、今回は画像の明るさをプログラムで分析する方法についてご紹介します。 本エントリーで紹介する技術は、例えば、ウェアラブルカメラで自動撮影した写真から極端に暗い写真や明るい写真を排除するといった用途で使えるのではないかと考えているところです。この用途での活用を考えているという点を踏まえて、これ以降をお読みください。

実験で用いた技術

私たちは画像の明るさを見える化するためにOpenCVというライブラリを用いることにしました。OpenCVとはコンピューターで画像や動画を処理するのに必要なさまざま機能が実装されているライブラリです。現在のところ、OpenCVは画像処理の定番ライブラリと言っても過言ではないため、知っている方も多いのではないでしょうか。

前提知識

ここでは、実験内容を理解していただくために知っておいていただきたい前提知識として、色空間と適性露出について記します。

色空間

コンピューターで画像の色を扱う上で、知っておくべきこととして色空間という概念があります。色空間とは、色の特性をいくつかの互いに独立した要素の組み合わせとして記述し、色の範囲を空間や立体に、個別の色を空間内の座標として表現したものです。最も有名な色空間としてRGB(Red Green Blue color model)があります。RGBは赤(Red)、緑(Green)、青(Blue)を色の要素としています。小学生の時に、光の三原色である赤と緑と青であらゆる色が作れるということを小学生の時に習ったと思います。RGBはそれを具現化した色空間と言えます。

色空間はRGBだけでなく様々あります。OpenCVではRGBの他に、HSV、YCrCb、LABの色空間が使えます。今回、私たちはHSVを用いることにしました。HSVは色相(Hue)、彩度(Saturation)、明度(Value)を色の要素としています。今回は明るさを扱いたかったのでHSVが最適だと考えたのです。

HSV色空間の視覚化図

HSV色空間の視覚化図 (出所:HSV色空間 – Wikipedia)

適性露出

露出とは写真用語で明るさのことを指します。それを踏まえて、適性露出という言葉を紹介します。適性露出とは、一般的にカメラが自動設定した適正な明るさ(見た目に近い、暗くも明るくもない)だと言われることがあります。しかし、撮影者が意図的に決定した露出こそが適性露出と言われることもあります。撮影者に目的があって、意図的に露出の調整をおこなって露出アンダーの写真をとったり、露出オーバーの写真を撮ったりすることがあるからです。

そのため、あらゆる写真に対して、プログラムが自動で露出が低過ぎる、あるいは高過ぎると判定することはできません。しかし、何事にも限度はありますので、どんな目的で使うにしても、露出が低過ぎるあるいは高過ぎるという写真をみつけることはできると考えました。今回の実験では、そのような写真を見つけることを目的としました。

実験内容

OpenCVを用いて、画像のピクセル単位で色の特性を色相(Hue)、彩度(Saturation)、明度(Value)に分解して、H・S・Vそれぞれの分布をヒストグラムで見える化しました。なお、Hは0~179、Sは0~255、Vは0~255の値をとります。その上で、Vの分布から暗過ぎるあるいは明る過ぎる写真を抽出するロジックを検討しました。

まず、よく見かける感じのスナップ写真を使ってヒストグラムの見方を説明します。画面左側が対象となる写真、真ん中がH・S・Vのヒストグラム、右側がヒストグラムのVのパーセンタイルです。ヒストグラムについては、縦軸が分布数(HSV各値ごとのピクセルの数)、横軸がHSV値を表しています。

特に注目していただきたいのは、明度(Value)のパーセンタイルです。明度が低い画素から順に並べたときの5%、50%、95%に対応する画素の明度を表したものになっています。そしてそれらをそれぞれ、5パーセンタイル、50パーセンタイル、95パーセンタイルと呼びます。上の写真の場合、Vの95パーセンタイルは150となっています。

暗い写真の場合

それでは、どう見ても暗過ぎる写真ではどうでしょうか。

Vの95パーセンタイルが67になりました。Vの95パーセンタイルに閾値(例えば、70未満)を設定すれば、露出が低く全体が暗過ぎる写真を見つけることができそうです。

次に、全体は暗いものの、一部分が明るくなっている写真ではどうでしょうか。

Vの95パーセンタイルが158になりました。全体が暗くても明るい部分の面積比が5ポイント以上あると95パーセンタイルの数字は高くなります。今回の例では、先のように95パーセンタイルが70未満だった場合に暗過ぎる写真と判定するロジックを適用したとしてもこの写真は含まれません。写真によってはこのロジックだと都合が悪い場合があるかもしれませんが、面積のほとんどが真っ暗な写真はどうみても暗い写真と言ってよいように思います。

明るい写真の場合

では、明るい写真ではどうでしょう。いわゆる白飛びしている画像で試してみました。

Vの5パーセンタイルが110になりました。Vの5パーセンタイルに閾値(例えば、100超)を設定すれば、露出が高く全体が明る過ぎる写真を見つけることができそうです。

しかし、そもそも背景も被写体も白い写真ではどうでしょう。

Vの5パーセンタイルが153になりました。先のように5パーセンタイルが100超だった場合に明る過ぎる写真と判定してしまうと、背景も被写体も白い写真では不都合がありそうです。

まとめ

今回のエントリーでは、画像の明るさをプログラムで分析する方法について実験した内容を紹介しました。実験では、具体的には、明度(Value)のヒストグラムのパーセンタイルの数字に閾値を設けて暗過ぎ/明る過ぎを判定する方法を分別することを試しました。実験の結果、暗過ぎの判定は使えそう、明る過ぎの方は背景や被写体によって使えないケースがありそうという感触を得ました。ウェアラブルカメラで自動撮影した写真の分別に使う場合には、撮影場所、天気、時間帯、被写体等のターゲットを絞り込んだ上で、改めてロジックの検討とパラメタ調整をしていく必要があると思いました。ひとまず今回は、OpenCVを用いて簡易的に画像の特性を要素分解して分析する方法を体得できたことが収穫でした。