(第2回)Python + OpenCV で遊んでみる(基本画像処理編)

(第2回)Python + OpenCV で遊んでみる(基本画像処理編)

目次

はじめに

前回は、Python(Anaconda)とOpenCVをインストールし、開発環境を構築しました。
 今回は、実際にOpenCVを利用して画像処理を行っていこうと思います。

結果出力について

 画像処理を行い、処理後の画像表示は主に以下の方法があります。

  • ファイル出力
  • 画面出力
  • Jupyter Notebookを利用し、Notebbook上でインライン表示

 それぞれについて、利用方法を下記します。

ファイル出力

 cv2.imwriteメソッドにてファイルを出力し、結果ファイルを保存します。

import cv2
img = cv2.imread('input.jpg')
cv2.imwrite('output.jpg',img)

画面出力

 cv2.imshowメソッドにて画像表示ウィンドウを表示します。
 imshowメソッドのみだと表示すると同時に終了してしまうため、キー入力による待機処理を使用します。

import cv2
img = cv2.imread('input.jpg')
cv2.imshow('Window Name',img)
cv2.waitKey(0) #キー入力待ちにして待機(0は無期限待機)
cv2.destroyAllWindows() #表示した画像表示ウィンドウを破棄

JupyterNotebookの利用

Jupyter Notebookとはプログラムを実行し、実行結果を記録出来るツールです。
Anacondaをインストールすると同梱されており、Pythonに限らず多種の言語を使用出来ます。

JupyterNotebookで画像をインライン表示する場合は、以下の2通りがあります。

matplotlibを利用

matplotlibとはグラフを作成・表示するPythonのライブラリです。

%matplotlib inline
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('input.jpg')
plt.imshow(img)

IPython.displayモジュールを利用

import cv2
from IPython.display import Image
Image('input.jpg')

今回はOpenCVでどのような画像処理が出来るのかを試すため、手軽なJupyter Notebook上でmatplotlibを利用した方法で表示していこうと思います。

基本的な画像処理

OpenCVで出来る基本的な画像処理を試していきます。
 今回、利用した画像は以下のポストの写真です。
(※記事投稿のため、実際の画像よりも縮小されております。画像処理後の結果も縮小して表示しております。)

インプット画像

グレースケール

まずはグレースケール表示です。いわゆる白黒写真です。
明暗のみの情報になるので画像処理ではよく使用されます。

%matplotlib inline
import cv2
import matplotlib.pyplot as plt

gry_img = cv2.imread('input.jpg', 0) #imreadの第2引数に0を指定するとグレースケールで読み込み

plt.gray() #matplotlibでグレースケールを使用する場合はグレースケールで読み込むように指定
plt.imshow(gry_img)

グレースケール

2値化

白と黒の2色のみで構成される画像に変換します。
cv2.thresholdメソッドを使用して、グレースケール画像から2値化します。

%matplotlib inline
import cv2
import matplotlib.pyplot as plt

gry_img = cv2.imread('input.jpg', 0) #グレースケールで読み込み
ret, threshold_img = cv2.threshold(gry_img, 127, 255, cv2.THRESH_OTSU) #第2,3引数は閾値、第4引数は手法のフラグ

plt.gray() #matplotlibでグレースケールを使用する場合はグレースケールで読み込むように指定
plt.imshow(threshold_img)
2値化

トリミング

画像の切り抜きを行います。

%matplotlib inline
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('input.jpg')
height = img.shape[0] #高さ
width = img.shape[1] #幅
trim_img = img[100:height, 100:width] #高さ(上)・幅(左)を100pixelずつ除く

trim_img = cv2.cvtColor(trim_img, cv2.COLOR_RGB2BGR) #matplotlibで表示する場合はRGBからBGRに変換
plt.imshow(trim_img)
トリミング
(若干わかりづらいですが、左上のハイビスカスが無くなっています。)

リサイズ

画像のサイズを変更します。(縮小、拡大)

%matplotlib inline
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('input.jpg')
height = img.shape[0] #高さ
width = img.shape[1] #幅
resize_img = cv2.resize(img, (int(width*0.5), int(height*0.5))) #サイズを×0.5で縮小

resize_img = cv2.cvtColor(resize_img, cv2.COLOR_RGB2BGR) #matplotlibで表示する場合はRGBからBGRに変換
plt.imshow(resize_img)
リサイズ

射影変換

ある平面を別の平面に射影する変換を行います。
 よく書類などをカメラで撮影して、正面からの平面に変換しているのをよく見かけますね。
 ここでは、numpyというPythonの数値計算ライブラリを使用します。

%matplotlib inline
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('input.jpg')
height, width, ch = img.shape #画像の大きさを取得

#points1の座標からpoints2の座標に変換するため、座標を指定
points1 = np.float32([[320,236],[1104,402],[12,332],[1053,640]])
points2 = np.float32([[0,0],[1250,0],[0,500],[1250,500]])

#透視変換の行列を求める
M = cv2.getPerspectiveTransform(points1, points2)

#画像を変換する
dst = cv2.warpPerspective(img, M, (1250,500))

dst = cv2.cvtColor(dst, cv2.COLOR_RGB2BGR) #matplotlibで表示する場合はRGBからBGRに変換
plt.imshow(dst)
射影変換

エッジ検出

画像の輪郭を検出します。

%matplotlib inline
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('input.jpg', 0) #グレースケールで読み込み
canny_img = cv2.Canny(img, 50, 110) #第2,3引数は閾値

plt.gray()
plt.imshow(canny_img)
エッジ検出

ぼかし

画像を平滑化させるガウシアンフィルタを用いて、画像にぼかし処理をいれます。
 ガウシアンフィルタにはカーネルサイズおよび標準偏差を調整して、ぼかし具合を調整します。
 どちらのパラメータも数値が大きくなるとぼかし具合が強くなります。
 標準偏差に0を指定すると、カーネルサイズ(正の奇数を指定)から自動計算されます。

%matplotlib inline
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('input.jpg')
gauss_img = cv2.GaussianBlur(img, (15,15), 0) #第2引数はカーネル、第3引数は標準偏差

gauss_img = cv2.cvtColor(gauss_img, cv2.COLOR_RGB2BGR) #matplotlibで表示する場合はRGBからBGRに変換
plt.imshow(gauss_img)
ぼかし
(わかりにくいですがぼけてます)

モザイク処理

画像のモザイク処理は、画像を一旦縮小し、元の大きさに拡大することでモザイク処理を施すことが出来ます。
(実際は縮小時に画素の平均化等のアルゴリズムが発生している)

%matplotlib inline
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('input.jpg')
orgsize = img.shape[:2][::-1]

img = cv2.resize(img, (int(orgsize[0]/20), int(orgsize[1]/20))) #画像を1/20に縮小
img = cv2.resize(img, orgsize) #画像を元のサイズに拡大

img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) #matplotlibで表示する場合はRGBからBGRに変換
plt.imshow(img)
モザイク処理

線の描画

line関数で画像に線を追加して描画します。

%matplotlib inline
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('input.jpg')
height = img.shape[0] #高さ
width = img.shape[1] #幅

img = cv2.line(img, (0,0), (width,height), (0,0,255), 5) #第2引数が始点、第3引数が終点、第4引数が色、第5引数が線の太さ
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) #matplotlibで表示する場合はRGBからBGRに変換
plt.imshow(img)
線の描画
(左上から右下に線を入れています)

おわりに

今回はOpenCVでどのような画像処理が出来るのか、基本的な処理を見ていきました。
次回は、顔検出分類器を使用して顔検出をして遊んでいきたいと思います。