PythonではOpenCVを使用することで画像処理が簡単に行うことができます。
画像処理は画像ごとのフォーマットが全然違うため全て自分で記述することはとても大変で、OpenCVを使うことで画像の読込/保存や画素値へのアクセスがとても容易になります。
『画像処理』というととても難しそうなことのように聞こえる方もいるかもしれませんが、実際には数行のコードだけで実現できてしまうので、この機会に画像処理の世界に足を突っ込んでみましょう!
この記事では、PythonとOpenCVを使った画像処理の基礎の実現方法を紹介します!
目次
OpenCVの導入
PythonでOpenCVを使えるようにするためには、お使いの環境にOpenCVを導入する必要があります。
PythonへのOpenCVの導入は、Anaconda-Navigator(以前の記事で紹介したバージョン管理ツール)から起動したターミナルで以下のコマンドを実行するだけです!
1 |
conda install -c conda-forge opencv |
コマンドが正常に実行できたら、以下のコマンドでエラーが出ないことを確認しましょう!
1 2 |
$ python $ import cv2 |
OpenCVで画像の入出力
さて、OpenCVの導入が完了したら実際にコードを書いていきましょう!
画像の読込
画像の読込は、imread関数を使用します。
1 2 |
# 画像の読込 img = cv2.imread("hoge.png") |
この一行だけで画像の読込は完了で、読み込まれたimg変数にはNumpy配列のndarrayとしてデータが格納されています。
本記事では、以下の画像を入力画像として説明を進めていくので、以下の画像をダウンロードして自分の環境でも使ってみてください。
画像の保存
画像の保存は、imwrite関数を使用します。
1 2 |
# 画像の保存 cv2.imwrite("result.png", img) |
この一行だけで画像の保存は完了で、指定されたパス(フォルダを指定していない場合はプログラムの場所)にファイルが保存されます。
対応する画像フォーマット
画像の読込および保存は、ファイルの拡張子から自動的にフォーマットを判断してくれるので、特にフォーマットを指定する必要はありません。
OpenCVで対応している画像のフォーマットは以下の通りです。
- jpg, jpeg, jpe, jp2
- png
- webp
- bmp
- pbm, pgm, ppm, pxm, pnm
- sr
- ras
- tiff, tif
- exr
- hdr
- pic
- dib
OpenCVで画像の表示
画像の読込を行なった後、画像の表示を行うにはimshow関数を使用します。
また、imshow関数の直後におまじないも追加しておきます。(おまじないがないと表示されません)
1 2 3 4 5 6 |
# 画像表示 cv2.imshow("WindowName", img) # キー入力待ち cv2.waitKey(0) # 全てのウィンドウを破棄 cv2.destroyAllWIndows() |
画像ウィンドウが表示された後に、何かキー入力をすればウィンドウが閉じます。
画像の画素値へアクセス
OpenCVで読み込んだ画像データはNumpy配列となっているので、添字にx座標とy座標を指定することで画素値にアクセスすることができます。
1 2 |
# (x, y)の画素値を取得 val = img[y][x] # [b, g, r]の値が格納された配列を取得 |
例えば、本記事の入力画像の(100, 100)の画素値は、[40, 56, 132]となります。
OpenCVで表色系のアレコレ
OpenCVで扱う表色系はデフォルトではRGB表色系となっていますが、グレースケールにしたりHSV表色系にしたりしてみましょう。
RGB成分の抽出
PythonのOpenCVで読み込んだ画像は、Numpy配列にBGRの順に格納されているため、スライスを使うことでRGBの各成分を抽出することができます。
1 2 3 4 5 6 7 8 9 10 11 12 |
# 赤成分用画像に元画像をコピー img_red = img.copy() # 赤成分を抽出 img_red[:,:,(0, 1)] = 0 # 緑成分用画像に元画像をコピー img_green = img.copy() # 緑成分を抽出 img_green[:,:,(0, 2)] = 0 # 青成分用画像に元画像をコピー img_blue = img.copy() # 青成分を抽出 img_blue[:,:,(1, 2)] = 0 |
また、RGBの各成分の輝度値のみを抽出したい場合は、split関数で画像を分割することもできます。
1 2 |
# RGB分解 img_blue, img_green, img_red = cv2.split(img) |
グレースケール化
OpenCVでグレースケール化を行う場合、cvtColor関数を使用します。
1 2 |
# グレースケール化 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
グレースケール化後の画像データは8bitデータとなる(カラー画像は24bitデータ)ので、画素値へアクセスした場合には[b, g, r]ではなく、輝度値のみとなります。
また、以降で紹介する画像処理の関数では入力画像が8bitデータである必要があるものもあるので、グレースケール化の方法は覚えておいた方が良いかと思います。
二値化
OpenCVで二値化を行う場合、threshold関数を使用します。
二値化の実現方法はいくつかありますが、一般的には判別分析法(大津の手法)と呼ばれる閾値を自動で設定する手法を用います。
1 2 |
# 二値化 th, bin = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) |
このとき、thには自動で設定された閾値が、binに二値化された画像データが格納されます。
threshold関数に渡す画像データはグレイスケール化済みの8bit画像データである必要があり、カラー画像を渡すとエラーとなります。
HSV表色系
OpenCVでHSV表色系への変換を行う場合、グレースケール化と同様にcvtColor関数を使用します。
1 2 |
# HSV表色系に変換 hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) |
内部データとしてはHSV表色系に変換されていても、画像を表示する際にはRGB表色系として表示されるため、それぞれ[H→B][S→G][V→R]として表示されています。
これらをRGBと同様に分割して確認してみましょう。
1 2 3 4 |
# HSV表色系に変換 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # H, S, Vに分割 h, s, v = cv2.split(img) |
それぞれの輝度値がHSVに対応する値となり、Hは[0-180]、Sは[0-255]、Vは[0-255]の範囲で表現されています。
平滑化フィルタ
多くの画像処理ではノイズ除去のために前処理として平滑化フィルタを用いることが一般的です。
ガウシアンフィルタ
OpenCVでガウシアンフィルタを行う場合、GaussianBlur関数を使用します。
1 2 |
# ガウシアンフィルタ gaus = cv2.GaussianBlur(image, (5, 5), 0) |
第二引数にはカーネルのサイズを渡しますが、これは平滑化の範囲のようなものだと思っておけば良いです。
第三引数〜第四引数(第四引数は省略しています)は各軸の標準偏差を表し、この値が大きいほどぼかしが強くなります。
メディアンフィルタ
OpenCVでメディアンフィルタを行う場合、medianBlur関数を使用します。
1 2 |
# メディアンフィルタ med = cv2.medianBlur(image, 5) |
第二引数にはカーネルのサイズを渡します。
まとめ
PythonとOpenCVを使った画像処理の基礎の実現方法について紹介を行いました!
ここで紹介したものは基礎中の基礎ですので、これらを前処理として使用してもっと難しいことに使われることが一般的です。
『画像処理』というと難しいことのように思われがちですが、見てもらった通り意外と簡単に実現できることが多いので、この機会に是非画像処理の世界に足を突っ込んでみてはいかがでしょうか。