ITいろいろ

プログラミングやクラウド、データ解析など、ITにかかわることをいろいろと書いています。

OpenCVでの画像のリサイズとpyplotで複数画像を表示

今回はOpenCVで画像をリサイズしてみます。 そして、今まではOpenCVの画像出力cv2.imshowを使っていたのですが、pyplotを使って複数の画像を一度に表示する方法も記述します。

コード紹介

# matplotlibのインストール(初回のみ)
!pip install matplotlib

# インポート
import cv2
import matplotlib.pyplot as plt

# 画像ファイルの読み込み
img = cv2.imread("Lenna.jpg")

# サイズを取得
height,width,color = img.shape

# リサイズ(指定した値でリサイズ)
img_resize1 = cv2.resize(img, dsize=(300, 100)) #dsize=は省略可

# リサイズ(倍率でリサイズ)
img_resize2 = cv2.resize(img, dsize=None, fx=0.5, fy=0.5)


# 左右3分割で左側に元画像を表示
plt.subplot(1, 3, 1)
plt.imshow(cv2.cvtColor(img_resize1,cv2.COLOR_BGR2RGB))

# 2番目にimg_resize1を表示
plt.subplot(1, 3, 2)
plt.imshow(cv2.cvtColor(img_resize2,cv2.COLOR_BGR2RGB))

# 3番目にimg_resize2を表示
plt.subplot(1, 3, 3)
plt.imshow(cv2.cvtColor(img_resize2,cv2.COLOR_BGR2RGB))

出力結果

少し解説

リサイズcv2.resizeについて

あまり説明することはないですが、dsizeパラメータは値の指定、fx, fyは倍率を指定できます。

dsizeは必須ですので、倍率で指定するときはdsize=Noneを忘れないようにつけましょう。

pyplotについて

plt.imshow関数で画像を表示することができます。

imshowの前にplt.subplotを設定することで複数画像を表示することができます。

plt.subplot(1, 3, 2)とすると、縦1行、横3列の枠の中で2番目に表示する、という意味になります。

注意点:OpenCVはBGR、PyplotはRGB

画像を表示するときに python plt.imshow(img) とやりたくなるのですが、そうするとレナさんの顔色が悪くなります。。

これは扱う配列の順番がOpenCVは[青、緑、赤]に対し、pyplotは[赤、緑、青]になるからです。

このため、コード紹介にあるように変換をしてから表示するようにする必要があります。

OpenCV/ガウシアンフィルタで画像をぼかす

今日はぼかしについて記述していきます。

コード紹介

# インポート
import cv2

# 画像ファイルの読み込み
img = cv2.imread("Lenna.jpg")

# ガウシアンフィルタでぼかす
img_blur = cv2.GaussianBlur(img, (9,7), 0)

# 読み込んだ画像の出力。
cv2.imshow('Lenna_sobel', img_blur)

# 何かのキーを入力待ちする。64bitのマシンの場合は「& 0xFF」が必要らしい
cv2.waitKey(0) & 0xFF
# ウィンドウを閉じる
cv2.destroyAllWindows()

出力結果

ちょっとだけぼけた。

引数の解説、変更

cv2.GaussianBlur(img, (9,7), 0)の第二引数、(9,7)はksize(カーネルサイズ)と呼ばれるもので、画像の中で横9ピクセル、縦7ピクセルを取り、その箱の中で各ピクセルの色を何にするのかを計算する形になっています。なのでこの箱を大きくすると、もう少し荒い(ぼけた)画像になります。

第三引数の0は、細かいことは分かりませんが、ぼけ度と思ってもらったらよいです。0は自動、1以上は大きくなるほどぼけ度が上がります。

img_blur = cv2.GaussianBlur(img, (15,13), 0)

img_blur = cv2.GaussianBlur(img, (15,13), 10)

終わりに

ぼかす方法はこの他にも平均値フィルタcv2.blur、中央値フィルタcv2.medianBlurなどありますが、ガウシアンフィルタがシンプルなコードでかつぼけ度を変えられるので、おすすめです。

OpenCVのエッジ検出の方法をいくつか紹介

今回はエッジ検出です。Pillowもエッジ検出の方法はあるようですが、いったんOpenCVを使った方法をまとめたいと思います。

エッジ検出の方法

今回は3つ紹介します。

  • Soble(ソーベル)法
  • Laplacian(ラプラシアン)法
  • Canny(キャニー)法

詳しいことはまだ無知なため割愛。。 使ってみてのおすすめはCanny(キャニー)法です。

Cannyを使ったエッジ検出

コード紹介

# インポート
import cv2

# 画像ファイルの読み込み
img = cv2.imread("Lenna.jpg")

# Cannyを使ったエッジ検出
img_canny = cv2.Canny(img, 100, 100)

# 読み込んだ画像の出力。
cv2.imshow('Lenna_canny', img_canny)

# 何かのキーを入力待ちする。64bitのマシンの場合は「& 0xFF」が必要らしい
cv2.waitKey(0) & 0xFF
# ウィンドウを閉じる
cv2.destroyAllWindows()

出力結果

少し解説

cv2.Cannyという関数を使います、第一引数には変換したい画像、第二引数と第三引数には閾値を入れます。 ここも詳細は分からないのですが、とりあえず両方100にしています。

その他のエッジ検出

ラプラシアン

# Laplacianを使ったエッジ検出
img_laplacian = cv2.Laplacian(img, cv2.CV_32F, 3)

ソーベル

# Sobelを使ったエッジ検出
img_sobel = cv2.Sobel(img, cv2.CV_32F, 1, 1, 3)

あまりエッジ検出、という感じの結果にはなりませんでした。 もう少し引数を変えるとうまくいくのかもしれません。 分かり次第またアップデートします。

OpenCV、Pillowそれぞれでグレースケール変換

前回までは画像の回転について書いていきましたが、今回は色調についても触れていきたいと思います。 単純な画像はPillowの方が使いやすいのですが、今後機械学習などを使うことを考えるとOpenCVの使い方も覚えた方がよいと思いますので、両方のやり方を記述していこうと思います。

OpenCVを使う方法

コードの紹介

# インポート
import cv2

# 画像ファイルの読み込み
img = cv2.imread("Lenna.jpg")

# グレースケールに変換
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 読み込んだ画像の出力。
cv2.imshow('Lenna_gray', img_gray)


# 何かのキーを入力待ちする。64bitのマシンの場合は「& 0xFF」が必要らしい
cv2.waitKey(0) & 0xFF
# ウィンドウを閉じる
cv2.destroyAllWindows()

出力結果

その他の画像変換

VS Codeでcv2.color_bgrと打つと、候補がいろいろと出てきます。 いろいろな変換ができるようですが、この辺りはまだ無知なので割愛。。

少し解説

BGR2xxxはBGR(青、緑、赤)の色調をxxxに変える、という意味になります。BGR2GRAYであればBGRをグレースケールに変換、という意味です。 ここで注意なのは、OpenCVRGBではなくBGRが基本になります。一般的にはRGBが多いので、少し厄介ですね。

Pillowを使う方法

コードの紹介

# インポート Pillow(PIL)の中のImageモジュールを使う
from PIL import Image

# 画像ファイルの読み込み
img = Image.open("Lenna.jpg")

# グレースケールに変換
img_gray = img.convert('L')

# 表示
img_gray

出力結果

Pillowを使ってもっと自由に画像を回転

前回OpenCVを使って画像を回転してみました。 ただ、回転は90度、180度、270度できないため、もっと自由に回転ができるPillowというライブラリを使ってみようと思います。

コードの紹介

# Pillowのインストール(初回のみ)
!pip install pillow


# インポート Pillow(PIL)の中のImageモジュールを使う
from PIL import Image

# 画像ファイルの読み込み
img = Image.open("Lenna.jpg")

# 時計回りに30度回転
img_30 = img.rotate(30)

# 表示
img_30

出力結果

回転できましたね。ソースもrotate(角度)ととてもシンプルです。

その他rotateのオプション

全画面表示

rotate(角度)だけだと、画像の縦横サイズは変わりません。そのため、画像が切れてしまいます。以下のようにexpandオプションを入れることで全画面表示することができます。

img_30 = img.rotate(30, expand=1)

回転軸を変える

通常は画像の中心を軸にして回転します。以下のようにcenterオプションに座標を入れることで、回転軸を変えることができます。

img_30 = img.rotate(30, center=(0,0))

画像を移動させる

先ほどの画面で少し上に寄ってしまったため、translateオプションで画像をずらすことができます。以下はy軸を100ずらしています。

img_30 = img.rotate(30, center=(0,0), translate=(0,100))

背景色を変える

filcolorオプションでRGBを指定することで、背景色を変えることができます。

img_30 = img.rotate(30, fillcolor=(255,0,0))

OpenCVとPillow、どっち?

結局どちらを使うのが良いかですが、

  • OpenCV:動画や分析などに便利  OpenCVにはUSBカメラなどから動画を取得することも簡単にできます。また取得した画像は配列で取得できるため、そこから機械学習などデータ分析をすることも可能なので、AIアプリを作る、などには向いています。

  • Pillow:単純な画像変換  今回の回転など、画像をちょっといじる分にはPillowの方が向いています。

また回転以外の処理方法などについてもこれから挙げていこうと思います!

OpenCVで画像を回転(90度、180度、270度)

画像を回転するには、OpenCVrotateを使います。

コードの紹介

# インポート(OpenCVを使うよ、という宣言)
import cv2

# 画像ファイルの読み込み
img = cv2.imread("Lenna.jpg")

# 時計回りに90度回転
img_90 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)

# 読み込んだ画像の出力。
cv2.imshow('Lenna_90rotate', img_90)


# 何かのキーを入力待ちする。64bitのマシンの場合は「& 0xFF」が必要らしい
cv2.waitKey(0) & 0xFF
# ウィンドウを閉じる
cv2.destroyAllWindows()

出力結果

画像を回転できました。

その他の角度で回転

どうもこのrotate関数、90度右回り、180度、90度左回り(270度右回り)しか対応していないようです。。

もう少し柔軟にできたらいいんですけどね。 また何か見つけましたら紹介したいと思います。

画像処理ライブラリのOpenCVをPythonで使う

今日は画像処理に取り組みます。

ライブラリについて

Pythonにはいくつものライブラリ(何かの処理をするためのまとまった関数のようなもの)が用意されていて、それをインストールするだけで様々な処理が簡単にできるようになります。

これがPython人気の理由の一つですね。

OpenCVのインストール

インストールの方法はいくつかありますが、pipというコマンドを使って、Jupyterでインストールします。

まずJupyterファイルを作ります。その前に、適当なフォルダを作り、「表示」→「ファイル拡張子」にチェックを入れておきましょう。

これってデフォルトでオフになってるんですよね。拡張子って何?っていう人向けに混乱させないようにしてるんでしょうけど、逆に混乱する気が・・・。

それはさておき、ウィンドウ上で、右クリック→新規作成→テキストドキュメントで、新しいファイルを作成します。

ファイル名を変更しましょう。ここでは「opencv.ipynb」としています。ファイル名は何でもよいですが、拡張子の.ipynbは間違えないようにしましょう。 拡張子変更してもよいか聞かれますので、「はい」と選択しましょう。

ファイルをダブルクリックで開くとVS CodeのJupyter Notebookが開きます。 ここで下記のように入力し、Shift+Enterで実行します。

!pip install opencv-python

pip install などのコマンドは通常コマンドプロンプトやPower Shellなどで実行するものですが、頭に「!」を入れるとJupyter Notebook上で実行ができます。

これでインストール完了です。

ついでにpipをアップグレード

結果を見ると「WARNING」とあり、pipに新しいバージョンがあると教えてくれます。 同じような要領で以下のように実行することでpipをアップグレードできます。

!pip install pip --upgrade --user

--upgradeオプションはインストールではなくアップグレードするよ、という意味。

--userはこのログインユーザの環境だけに適用する、という意味です。

--userをつけないとアクセス権がないとエラーになったためつけています。

OpenCVで画像を表示してみる。

事前に何かの画像をipynbファイルを入れたフォルダに入れておきます。今回は画像処理に有名なレナ画像を入れていますが、何でもよいです。

VS Codeに戻り、プログラムを入力します。単純に画像を表示するプログラムです。

# インポート(OpenCVを使うよ、という宣言)
import cv2

# 画像ファイルの読み込み
img = cv2.imread("Lenna.jpg")

# 読み込んだ画像の出力。ウィンドウのタイトルを「Lennaさん」とする
cv2.imshow('Lennaさん', img)
# 何かのキーを入力待ちする。64bitのマシンの場合は「& 0xFF」が必要らしい
cv2.waitKey(0) & 0xFF
# ウィンドウを閉じる
cv2.destroyAllWindows()

Shift+Enterで実行するとレナさんが表示されます。

ちなみにこのopencv、日本語には対応していないようです。

ですので、タイトルが文字化けしてしまいます・・・。

特にパスに日本語が入っているとエラーになるので注意して下さい。

少し解説

大体コメントアウトで書いている通りなのですが、 cv2.waitKey(0)の引数について少し触れます。 このwaitKeyの引数は、何ミリ秒待つかを指定できます。 例えばcv2.waitKey(5000)とすると、5,000ミリ秒=5秒だけ待ちます。 0にすると、無限に待ちます。つまり何かキーが入力されるまで待ち続ける、という仕組みにできます。

おわりに

いかがでしたでしょうか。文字化け問題は本当につらいですね。。日本人としては一生付き合わないといけないのかもしれません。