データサイエンス&サイバーセキュリティ備忘録

Python, Data Science, Kaggle, Cyber Security, CTF, などなど

Python + OpenCVの勉強会に参加しました

2020年1月26日、日本マイクロソフト株式会社でPyLadies Tokyoが主催するPython + OpenCVの勉強会に参加してきました。

PyLadiesとは、Pythonが好きな女性のためのコミュニティであり、全世界に各支部があるそうです。

日本には、東京・京都・沖縄の3つの支部があるとご紹介がありました。
今回は、東京支部のmeetupということで、OpenCVをマスターしてインスタグラムやSNOWのように画像を加工して遊ぶという内容でした。

今までOpenCVを使用したことがありませんでしたが、基礎から丁寧に説明してくださったので非常に分かりやすかったです。

OpenCVとは何か、どのようにJupyter Notebook上でPythonコードを書くかを簡単にですがまとめたいと思います。

OpenCVとは

画像処理(色、サイズの編集や画像のnumpy/幾何学変換)や画像解析(特徴・物体検出)のためのオープンソースライブラリです。

加工した画像を、scikit-learnやKerasといった機械学習ライブラリと組み合わせることができ、人物検出などを行うことが可能です。

対応言語はPythonだけでなく、C++Javaも含まれているとのことです。

事前準備

OpenCVを使うためには、まずライブラリをインストールする必要があります。

私の場合は、Anaconda Promptを使用して以下のコマンドでインストールしました。

pip install opencv-python

ライブラリのインポート、ファイル読込みと表示

コードは以下の通りです。

# OpenCVのインポート
import cv2
# 読み込んだ画像を表示させるために必要
import matplotlib.pyplot as plt
# Jupyter Notebook上でインライン表示させる
%matplotlib inline


# 画像ファイルの読込
# "imgName.jpg"は読み込みたい画像のファイル名
img = cv2.imread("imgName.jpg")

# 色空間の変換 (注1)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 画像ファイルの表示
plt.imshow(img_rgb)
plt.show()

(注1) OpenCVはBGR空間(色の情報がBlue, Green, Redの順で保持)であるのに対し、matplotlibはRGB空間(Red, Green, Blue)なので変換が必要です。

変換せずに出力するとどうなるかは、ぜひ試してみてください。

グレースケール空間への変換

cv2.cvtColor()の関数を使用して他の色空間に変換することも可能です。

色空間は様々な種類がありますが、今回はグレースケール空間への変換の方法を紹介します。

画像をグレースケール空間に変換するということは、色の情報が必要のない処理において、色の情報を落とすことによってデータ量と処理を軽くするというメリットがあるとのことです。

上記のコードで読み込んだ画像(変数 img)をグレースケール空間へ変換して出力するコードは以下の通りです。

# 読み込んだ画像をモノクロにする
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# (注2)
plt.imshow(cv2.cvtColor(gray, cv2.COLOR_BGR2RGB))
plt.show()

(注2) 変数grayは既にモノクロだから色空間の変換が必要でないように見えますが、おそらくimshow()というBGR空間であるOpenCVの関数で表示させようとしているため、BGR空間からRGB空間に変換する必要があります。

ファイルの書き出し

OpenCVでファイルの書き出しを行うには、imwrite()という関数を使用します。

上記のコードでグレースケール空間に変換した画像を書きだそうと思います。

コードは以下の通りです。

# "gray.jpg"はファイル名、拡張子(.jpg)をつけ忘れない
cv2.imwrite("gray.jpg", gray)

これで、モノクロに変換した画像がgray.jpgというファイル名で保存されます。

その他の画像加工テクニック

この記事の先頭の方に書いた通り、今回はOpenCVでインスタグラムやSNOWのように画像を加工するというイベントでした。

なので、画像にフィルターをかけたような色変換をしたり、bit変換を行ってネガポジ反転させる方法も学びました。

それぞれのコードの書きかたは以下の通りです。

# カラーマップ変換
# applyColorMap()関数で他のカラーマップに変換
# 今回はCOLORMAP_INFERNOというカラーマップに変換
# カラーマップは今回教えていただいたものだけでも15種類もある
color_map = cv2.applyColorMap(img, cv2.COLORMAP_INFERNO) 

plt.imshow(cv2.cvtColor(color_map, cv2.COLOR_BGR2RGB))
plt.show()
# ネガポジ反転
# bitwise_not()関数で色の情報を反転
inversion = cv2.bitwise_not(img)

plt.imshow(cv2.cvtColor(inversion, cv2.COLOR_BGR2RGB))
plt.show()

機械学習用の画像加工テクニック

勉強会では、エッジ検出のコードの書き方も教えていただきました。

機械学習でエッジ検出を行う場合は前処理をしてからの方が良いとのことです。

エッジ検出のアルゴリズムはいくつかあるみたいで、今回はCanny(キャニー)法を学びました。

OpenCVのサイトに理論が記載されてますので、ご紹介します。

labs.eecs.tottori-u.ac.jp

以下がCanny法によるエッジ検出のコードになります。

# 0は最小閾値、80は最大閾値
# 閾値はCanny法検出内ので行われるヒステリシス式閾値処理に利用
# ヒステリシス式閾値処理については上記のサイトを参照
edge = cv2.Canny(img, 0, 80)

plt.imshow(cv2.cvtColor(edge, cv2.COLOR_BGR2RGB))
plt.show()

まとめ

今回はOpenCVで画像の読込み、書き出し、加工の仕方を学びました。

勉強会の趣旨の通り、OpenCVで画像を加工して遊ぶ目的で参加しました。

画像処理は難しそうというイメージを持っていましたが、一つ一つの処理は実は簡単であり、複数の処理を組み合わせで高度な処理ができることが分かりました。

エッジ検出に関してはKaggleの画像コンペで活かせそうな気がするので、今度使ってみたいと思います。