Help us understand the problem. What is going on with this article?

OpenCV3をPython3で動かす。画像データ分析入門の為の下準備。

More than 1 year has passed since last update.

はじめに

Pythonを使った画像のハンドリングについての記事となります。
自分自身の勉強と知識の整理という目的で本記事を書きました。技術ブログ投稿は初なので、暖かい目でご容赦いただけると幸いです。

OpenCV3をインストール

以下の環境で行いました。

macOS 10.14.2
Python 3.6.5
anaconda3-5.2.0
Jupyter Notebook

(19/01/25 記載)
現状ですと、以下の通りにインストールすると、手取り早いようです。

$ pip install opencv-python

なお、pyenvによる仮想環境設定については、今回は割愛します。

OpenCV3の動作確認

まず、正しくOpenCV3がimportされているかどうかを確認します。

import numpy as np
import cv2, matplotlib
import matplotlib.pyplot as plt

print(cv2.__version__)

エラーが出ずversion表示されればOKです。

画像入力と画像表示

まず、今回はjupyterで動かしながら、画像の埋め込み表示を行います。matplotlibを使いますが、以下のおまじないを書きます。

%matplotlib inline

次に、画像分野で良く使われているlennaの画像をググって入手し、画像を読み込んで表示します。
RGBへの変換も必要です。

%matplotlib inline
def read_img(name_i):
    img = cv2.imread(name_i)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    return img

# 画像の読み込み
img = read_img('lenna.png')

# 画像の表示
plt.imshow(img)

スクリーンショット 2016-12-18 22.46.55.png

lennaさんが無事に表示されました。

顔認識と顔座標の検出

引数:画像ファイル名,顔認識の特徴量パス
返り値:画像ファイルから検出された顔画像の配列

で、以下の処理を行います。

・画像入力
・入力画像をグレー画像に変換
・顔認識実行。特徴量のpathを引数から入力。
・検出した顔を囲む矩形を作成し、1枚の画像ずつ、配列へ追加。
・画像に枠を枠を書く
・画像の表示

def detect_face(img_name , cascade_path):
    #画像入力
    img = read_img(img_name)
    width = img.shape[1]
    height = img.shape[0]
    img = cv2.resize(img , (width , height))

    #入力画像をグレー画像に変換    
    gry = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    #顔認識実行。特徴量のpathを引数から入力。
    cascade = cv2.CascadeClassifier(cascade_path)

    #minNeighbors=20, minSize=(30, 30)→検出枠が近すぎるのと、小さすぎるのは間引く。
    facerect = cascade.detectMultiScale(gry, scaleFactor=1.05, minNeighbors=20, minSize=(30, 30))
    dst_img = []
    if len(facerect) > 0:
        color = (255, 0, 0)
        for rect in facerect:
            x = rect[0]
            y = rect[1]
            w = rect[2]
            h = rect[3]
            #検出した顔を囲む矩形を作成し、1枚の画像ずつ追加。
            add_image = cv2.resize(img[y : y+h , x : x + w] , (64 , 64))
            dst_img.append(add_image)

            #画像に枠を枠を書く
            cv2.rectangle(img, tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]), color, thickness=2)
        # 画像の表示
        plt.imshow(img)

    return dst_img

以下、openCVであらかじめ持っている学習済み顔特徴量を指定し、実行。

cascade_path = '/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml'
res_images = detect_face("lenna.png" ,  cascade_path)

スクリーンショット 2016-12-18 22.47.08.png

lennaさんの顔が赤い枠で囲まれました。

次に、顔検出の画像のみを表示します。今回は1画像から検出顔を1つなので、indexは0番目です。

plt.imshow(res_images[0])

スクリーンショット 2016-12-18 22.47.17.png

1枚の画像から複数顔検出

1枚の画像から複数顔の検出を行う場合です。
画像の引用元は以下になります。
https://www.pakutaso.com/model.html

res_images = detect_face("sample.png" , cascade_path)

スクリーンショット 2016-12-18 22.47.24.png
このような実行結果となりました。真正面でないと検出されないようです。

また、複数の画像を保持できているかの確認のため、0番目以外の画像で表示されるかを確認します。今回はindexが1で実行します。

plt.imshow(res_images[1])

スクリーンショット 2016-12-18 22.47.41.png

ヒストグラム算出と基本的な統計量の算出

ごく基本な統計量に注目するということで、ヒストグラムを算出します。

#Green画素のみを抽出し、Green画像でヒストグラム算出
RGB =cv2.split(res_images[1])
Gr = RGB[1]
hist = cv2.calcHist([Gr],[0],None,[256],[0,256])
hist

スクリーンショット 2016-12-18 22.47.59.png
配列でヒストグラムを持つことができます。
次にプロットします。

plt.plot(hist)
plt.xlim([0,256])
plt.show()

スクリーンショット 2016-12-18 22.48.10.png

サチっているというか、明るめの画像なので、真面目に分析を行い際には、正規化も必要になるでしょう。

得られたヒストグラムに対して、基本的な統計量を見て見ます。

print("積算値:", np.sum(hist))
print("最大値:", np.max(hist))
print("最小値:", np.min(hist))
print("平均値:", np.mean(hist))
print("中央値:", np.median(hist))
print("分散値:", np.var(hist))

スクリーンショット 2016-12-18 22.48.17.png

今回はここで終わりです

OpenCVのちょっとした動作確認も行いつつ、基本的な統計量を算出することまでできました。
統計量だけで考えなくても、世の中に画像特徴量の作成方法はたくさんあります。また、作成した特徴量に対してbag-of-featuresの形式にすれば、特徴量エンジニアリングを行ったことになり、機械学習実践の第一歩を踏み出せるかと思います。実務的なところは、また別の機会で紹介できたらと思います。

tawash
enigmo
株式会社エニグモは、ソーシャルショッピングサイト「BUYMA(バイマ)」を運営する会社です。
https://www.enigmo.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away