4
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

OpenCVで簡単に実装できる画像前処理

Last updated at Posted at 2021-04-09

調べて実装して、評価してみた。あとアイデアをひとつだけ。

概要

  1. OpenCV で簡単に実装できる画像前処理を調べて実装したよ
  2. 実際に Object Detection する前に適用して評価したよ
  3. 結果は・・・微妙だったよ

モチベーション

Object Detection モデルは開発者が公開している pre-trained weight を使って遊んでいるだけの私だけど、モデルに入れる前の画像を前処理してモデルが判断しやすいようにすること、そしてモデルの出力を選別したり綺麗に整形したりするのは、使う側の責任だろうと。

ということで今回は画像前処理について実際にやってみたので、そのまとめをば。(要するに備忘録)
私は画像が専門じゃないので、OpenCV を使って簡単に実装できたものだけを。

画像は全て COCO 2017val に含まれていたものです。使っている Object Detection モデルは yolov5m で、ONNX で動かしています。もちろん使っているのはコレ。

昼白色が強い画像の場合(ホワイトバランス調整)

特に室内の画像の場合、照明の昼白色が強くて「黄色いなオイ!」と思うことが時々ある。
そういう場合はホワイトバランスの調整をして、なるべく自然色に戻してあげた方が良いんじゃないかと。

import numpy as np
import cv2

def adjust_white_balance(image: np.ndarray) -> np.ndarray:
    # white balance adjustment for strong neutral white
    image = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
    avg_a = np.average(image[:, :, 1])
    avg_b = np.average(image[:, :, 2])
    image[:, :, 1] = image[:, :, 1] - (
        (avg_a - 128) * (image[:, :, 0] / 255.0) * 1.1
    )
    image[:, :, 2] = image[:, :, 2] - (
        (avg_b - 128) * (image[:, :, 0] / 255.0) * 1.1
    )
    image = cv2.cvtColor(image, cv2.COLOR_LAB2BGR)
    return image

BGR を Lab色空間に変換して、ゴニョゴニョするだけ。

white_balance.png
ホワイトバランス調整の例1(左:調整なし、右:調整あり)

ノイズ除去(Gaussian Blur)

性能が悪いカメラだと、ノイズが乗っちゃってることがある。そういう場合はノイズ除去。

import numpy as np
import cv2

def smooth_image(image: np.ndarray) -> np.ndarray:
    # image smoothing for noise removal
    return cv2.GaussianBlur(image, (5, 5), 0)

めちゃ簡単。GaussianBlur で、要するにボカしてノイズを分からないようにする。

smoothing.png
ノイズ除去の例2(左:除去なし、右:除去あり)

ノイズは、カメラの性能だけじゃなくて、例えば雨なんかもノイズの一種と見做すことが出来る。

smoothing_2.png
ノイズ除去の例3(左:除去なし、右:除去あり)

暗い部分を明るくする(コントラスト調整)

暗くてよく分かんないのは、明るくしてあげたい。

import numpy as np
import cv2

def correct_contrast(image: np.ndarray) -> np.ndarray:
    # contrast correction that brightens dark areas
    b = 10  # HEURISTIC !!
    gamma = 1 / np.sqrt(image.mean()) * b
    g_table = np.array([
        ((i / 255.0) ** (1 / gamma)) * 255
        for i in np.arange(0, 256)
    ]).astype("uint8")
    return cv2.LUT(image, g_table)

contrast.png
コントラスト調整の例4(左:調整なし、右:調整あり)

暗くなると言えば逆光だが、ちょっとは効果がある。
contrast_2.png
コントラスト調整の例5(左:調整なし、右:調整あり)

やってみたけど使わないと判断したもの

ヒストグラム平坦化

import numpy as np
import cv2

def levelize_histogram(image: np.ndarray) -> np.ndarray:
    # make color distributions even
    for i in range(3):
        image[:, :, i] = cv2.equalizeHist(image[:, :, i])
    return image

暗い所を明るくするという意味で、色の分布を平坦化すればいいんじゃないの、という方法。
画像全体がすごい真っ暗!という場合は効果があるけど、普通の画像にやっちゃうと色が凄い事になっちゃうので、パス。

固定値を使ったコントラスト調整

import numpy as np
import cv2

def correct_contrast_using_lut(image: np.ndarray) -> np.ndarray:
    # contrast correction using look-up-table
    a = 10
    c_table = np.array([
        255.0 / (1 + np.exp(-a * (i - 128) / 255))
        for i in np.arange(0, 256)
    ]).astype("uint8")
    return cv2.LUT(image, c_table)

前に出したコントラスト調整は、画像のRGBの値の平均を使っているけど、これは固定値でやるパターン。これも凄いことになっちゃう。

Super-Resolution を使った鮮明化

COCOデータセットの中には、かなりボケてたりブレてたりする画像がある。こいつらを根本的にどうにかしたいなぁと考えて、思いついた。
Super-Resolution(超解像)使えばいいんじゃね?」

dnn_superres を使うので、Python Library として普通の opencv-python じゃなくて opencv-contrib-python をインストールすることが必要です。

import numpy as np
import cv2
from cv2 import dnn_superres, dnn_superres_DnnSuperResImpl

sr = dnn_superres.DnnSuperResImpl_create()
sr.readModel('superres/ESPCN_x4.pb')
sr.setModel('espcn', 4)

def upsample_image(
    image: np.ndarray,
    sr: dnn_superres_DnnSuperResImpl
) -> np.ndarray:
    # increase resolution with super-resolution to make the image clearer
    # and then shrink the image
    prev_height = image.shape[0]
    prev_width = image.shape[1]
    # sr.upsample() (super-resolution) is too slow when the image is big
    # so, do super-resolution after shrinking image
    image = cv2.resize(
        image, (prev_width // 2, prev_height // 2),
        interpolation=cv2.INTER_AREA
    )
    image = sr.upsample(image)
    # restore image size
    image = cv2.resize(
        image, (prev_width, prev_height),
        interpolation=cv2.INTER_AREA
    )
    return image

適当なサンプルプログラムで済まない。

  1. SuperResolutionのモデルとしては、一番高速なESPCNを使う
  2. ESPCNと言えども、画像のサイズが大きいと時間がかかるので、まずは半分に縮小する
  3. ESPCN で4倍に拡大する
  4. それをまた半分に縮小して、元のサイズに戻す

意図としては

  1. 画像を縮小することでそもそもノイズを減らす効果を期待
  2. 拡大に単なる補間ではない SuperResolution を使うことで、さらに滑らかになることを期待

superres.png
SuperResolutionをやった例6(左:やってない、右:やった)

性能

coco dataset 2017val からランダムに1000枚を選んで計測した。

  • no_image_clarify: 画像前処理なし
  • white_balance: ホワイトバランス調整のみ
  • smoothing: ノイズ除去のみ
  • contrast: コントラスト調整のみ
  • superres: SuperResolutionのみ
  • all: 上記全部入り(画像に適用した順番は上の通り)
  • all2: コントラスト調整すると、ノイズが乗ったみたいになるので、コントラスト調整したあとにノイズ除去した
  • all2_no_superres: all2 から SuperResolution だけやめる

所要時間

画像1枚あたりの平均
time.png
なんで all が前処理単体よりも低いんや・・・まぁ、Object Detection モデルの inference に要する時間に比べると、どれも誤差の範囲内ってことなんだろう。

精度

map.png
入れれば入れるほど落ちてるやんけ・・・

まとめ

  • 前処理を入れれば入れるほど精度が落ちてるのは、結局、特殊な画像だと良くなったように見えるけど、全体に対して一律に適用しちゃうと悪影響を及ぼすということなんだろうな
  • 作っては見たものの、デフォルトで OFF にするよう修正します・・・
  • ちゃんと評価して良かった(今日の良かった探し)
  1. http://farm1.staticflickr.com/147/434840964_a9c5bc3b58_z.jpg
    confidence score 的には大して変わってないけど、真ん中の人やソファーの上の laptop のスコアがちょっと上がってるか。

  2. http://farm4.staticflickr.com/3265/5839036384_1ecac4f59a_z.jpg
    よく見ると分かるけど、元のザラザラしたノイズがすっきりしている。
    Object Detection 的にも、上部の大きな bowl がギリギリ認識できるようになった。

  3. http://farm1.staticflickr.com/5/7213514_c15cc3c285_z.jpg
    この場合、車も消火栓も confidence score が上がっている。

  4. http://farm2.staticflickr.com/1100/538718655_aef41a4977_z.jpg
    traffic light が1個消えちゃったけど、車の confidence score は上昇している。

  5. http://farm6.staticflickr.com/5184/5694114164_e2a5d24659_z.jpg
    右側では、海に入っているサーファーを頑張って認識しようとしているのが分かる。

  6. http://farm3.staticflickr.com/2258/2269567997_08065fe404_z.jpg
    こんなブレブレのやつでも、ちょっとはマシになるかな、と。

4
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?