OpenCVで画像の前処理をしてみよう!

所要時間

100分

学ぶコト

・OpenCVを使った画像の加工・修正・変換

ここでは、画像処理において重要なOpenCVの使い方を学んでいきます。

OpenCV“とは正式名称を「Open Source Computer Vision Library」と言う、コンピュータービジョン・画像認識の領域でよく使われるライブラリです!

Pythonで利用されることが多いですが、C+やJavaといった他の言語でも利用できます。

OpenCVを使うことで

  • 画像の読み取り
  • 画像の編集
  • 特徴量の抽出
  • 画像の識別

といったことが出来るようになります!

OpenCVで画像を取得して表示

まずはOpenCVで画像を取得して表示していきましょう!

ここではPythonの実行環境としてGoogle Colabを使っていきます。

まず、以下のように記述してみましょう!

from google.colab.patches import cv2_imshow
import cv2

# 画像を読み込む
image = cv2.imread('/content/sam.jpeg')

# 画像を表示する
cv2_imshow(image)

# 画像を別の形式で保存する
cv2.imwrite('/content/sam.png', image)

この時、以下のOpenAIの天才CEOサムアルトマンの画像を特定のディレクトリに格納して使っています。

サムアルトマン
(出典:wikipedia: サム・アルトマン

ご自身の環境で動かす際は、ご自身の好きな画像を特定のディレクトリに格納しそのディレクトリパスを指定するようにしてください。

ここの処理では画像を取得し表示した上で別の拡張子で保存しています。

cv2.imreadで画像を取得しています
・画像の表示にはcv2.imshowではなくcv2_imshowを使っていますので注意してください。cv2.imshowはJupyterのセッションをクラッシュさせるためにエラーが出てしまいます。cv2_imshowはGoogle Colabのみで使えるので注意してください。
cv2.imwriteを使うことで拡張子を変更することができます

OpenCVで画像を加工(基礎)

続いてOpenCVを使って色んな方法で画像を加工していきましょう!

先ほど取得したサムアルトマンの画像は192×262ですのでそれを前提に加工していきます。

# 色空間を変換する(例:BGRからグレースケールへ)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2_imshow(gray_image)

# 画像をリサイズする
resized_image = cv2.resize(image, (100, 100))
cv2_imshow(resized_image)

# 画像を回転する
(h, w) = image.shape[:2]
center = (w / 2, h / 2)
M = cv2.getRotationMatrix2D(center, 90, 1)
rotated_image = cv2.warpAffine(image, M, (w, h))
cv2_imshow(rotated_image)

# 画像をトリミングする
cropped_image = image[0:100, 0:100]
cv2_imshow(cropped_image)

※ご自身で用意した画像を利用する場合はサイズの設定などを合わせて実行してください。

・カラー画像をグレースケールに変更する処理
・リサイズする処理
・画像を回転させる処理
・画像をトリミングする処理

の4つの処理をそれぞれかけて表示しています。

結果は順番に以下のようになりました。

sam
グレースケール
sam
リサイズ
sam
回転
sam
トリミング

それぞれちゃんと画像変換できていることがわかります。

OpenCVで画像を加工(応用)

ここからは少し応用的な加工方法を見ていきましょう!

まず画像の明暗の境界線を検出するエッジ検出をしていきましょう!

以下のように記述します。

# エッジ検出
# Cannyエッジ検出器の閾値を設定(低い閾値:50、高い閾値:150)
edges = cv2.Canny(image, 50, 150)
cv2_imshow(edges)

結果は以下のようになりました。

sam

ちゃんと境界線らしき箇所が検出できていることがわかります。

続いて、画像をぼやかしていきます。

# 画像をぼかす
# カーネルサイズ(幅:5、高さ:5)、標準偏差(sigmaX:0)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
cv2_imshow(blurred)

結果は以下のようになりました。

sam

画像がぼやけていることがわかりますね!

この時、cv2.GaussianBlur(image, (5, 5), 0)のパラメータである(5, 5)は、ガウシアンカーネル(画像のフィルタ的な役割)の高さと幅を指します。カーネルサイズが大きいほど、ぼかし効果は強くなります。

最後の0はガウシアン関数の標準偏差を表し、ぼかしの広がりを決定します。標準偏差が大きいほど、ぼかしは広範囲に渡ります。0を指定すると、カーネルサイズから自動的に標準偏差が計算されます。

試しにカーネルサイズを大きくしてぼかしを強くしてみましょう!

blurred = cv2.GaussianBlur(image, (15, 15), 0)
cv2_imshow(blurred)

結果は以下のようになります。

sam

かなりぼかしが強くなっていることがわかりますね!

ではぼかしを除外するにはどうすればよいのでしょうか?

以下のように記述することで画像のコントラストを強調してぼかしを除去することができます。

# 画像をぼかす
# カーネルサイズ(幅:5、高さ:5)、標準偏差(sigmaX:0)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
cv2_imshow(blurred)

# 画像のぼかしを除去する
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
filtered_image = cv2.filter2D(blurred, -1, kernel)
cv2_imshow(filtered_image)

numpyで3×3のフィルタを作成しそれを元に画像のコントラストを強調しています。

3×3の中心に5が来ることになりその隣接した上下左右に-1が来ています。

このカーネルを画像に適用すると、中央のピクセルの値が強調され、周囲のピクセルの値との対比が増し、結果的に画像のエッジや細部がより明瞭になるのです!

結果は以下のようになりました。

sam

画像のぼやけが取れて鮮明になっていることがわかります。

課題

自分の独自画像を使って、ここで学んだOpenCVの処理の流れを実行していこう!