画像・音声処理

【1分でわかる】初心者でも簡単にOpenCVで画像認識の実装ができるやり方を学ぶ!

画像認識といえばOpenCVの名を聞いたことがある方は多いと思います。OpenCVは様々なことができて便利ですが、

画像サイズを変えるコードはなんだっけ?

OpenCVでどんなことができたっけ?

と、確認したくなることもあると思います。今回はOpenCVとはなに?という疑問から、何ができるのか。なんでこんなことをするのかまで解説していこうと思います。


本ブログを運営しているTech Teacherは、
プログラミング家庭教師サービスを運営しています。
完全マンツーマン・フルオーダーメイド
あなたが必要な指導を提供します。

OpenCVとは

OpenCVオープンソースのコンピュータビジョン用ライブラリです。

OpenCVの概要と基本は上記のページに記述がありますので、今回は機械学習で画像処理をする前提で、何のために何をするかという点に注目して実装方法を確認していきたいと思います。

何のためにOpenCVを使うの?

OpenCVは、主に

  • 画像・動画の読み込み
  • 画像処理
  • 画像認識

などを行うことができます。今回は機械学習に特化して解説しますが、画像に関する様々なことを行えます。

また、画像の機械学習というとニューラルネットワークで認識するイメージがありますが、OpenCVで対象物を明確にしてからニューラルネットワークで処理したり、OpenCVで前処理を行ったものを数値として機械学習することにより不良認識をしたりすることもあります。

OpenCVの使い方

画像認識でOpenCVを使用することを前提に、どのような操作を行うか、実際にコードを見ながら処理を確認していきます。

インストールや概要については以下の記事を参照していただければと思います。

Python + OpenCVで画像処理をマスター!使用法・実用例を解説Python初心者の方でOpenCVの使い方について悩んでいる人必見。OpenCVの基礎知識やインストール方法、使い方を網羅しました。OpenCVを使用した画像動画処理について悩んでいる人は参考にしてください。...

事前準備

ライブラリのインポート

まずはOpenCVのPython用ライブラリ「cv2」をインポートしておきます。そのほか、必要なものをまとめてインポートします。

import cv2
import numpy as np

画像の呼び出し

画像データを確認するにも、画像データを編集するにもまずは画像を呼び出します。

img = cv2.imread('./Sample.jpg')

画像の表示

解析する前に画像を表示して確認します。

cv2.imshow('Image', img)
cv2.waitKey()

画像のサイズ変更

データの前処理として、まずはデータサイズをそろえるためなどにサイズ変更をします。方法は以下のとおり。

img0 = cv2.resize(img,(250,180))

念のためにサイズ変更後、どうなったか確認します。

cv2.imshow('Image', img0)
cv2.waitKey()

画像の保存

画像サイズを変更したものは解析用に保存します。

cv2.imwrite('./Sample_2.jpg', img0)

グレースケールで読み込む

先ほどはカラーで読み込みましたが、実際にはグレースケールで読み込んで解析をすることも多くあります。グレースケールで読み込んで表示してみます。読み込み時に引数に「0」を指定するだけです

img = cv2.imread('./Sample.jpg', 0)
cv2.imshow('Image', img)
cv2.waitKey()

BGR-RGB変換

こちらも解析前に対応が必要な場合があります。カラーの表示がBGRの順番になっている場合(下図のような色表示になります)RGBの順に直して正しい色にしてやる必要があります

im = matplotlib.image.imread("./Sample_4.jpg")
plt.imshow(im)

以下のように変換をかけて色をもとに戻します。

img_4 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imshow('Image', img_4)
cv2.waitKey()

元データを調整する

データから対象となる部分を切り出したり、データの不足などにより画像に一部変更を加えて画像を水増しすることがあります。その際に画像自体に変更を加える方法です。以降は解説内容に集中して説明するために、グレースケール画像で説明します。

画像の平行移動

画像をアフィン変換することにより画像を移動します。わかりやすいように移動距離部分をアフィン変換行列から抜き出して記述しています。Mがアフィン変換行列です。

img = cv2.imread('./Sample.jpg', 0)
x, y = 50, 30
M = np.float32([[1, 0, x],
                 [0, 1, y]])
img_m = cv2.warpAffine(img, M, (480, 360))
cv2.imshow('Image', img_m)
cv2.waitKey()

画像の拡大・縮小①

resizeをすると画像の拡大縮小ができます。

img_re_1 = cv2.imread('./Sample.jpg', 0)
img_rs_1 = cv2.resize(img_re_1, (100, 200))
cv2.imshow('Image', img_rs_1)
cv2.waitKey()

まずは画像サイズを指定してサイズ変更します。「cv2.resize(img,(100, 200))」の「(100, 200)」で変換後サイズを指定します。

img_re_2 = cv2.imread('./Sample.jpg', 0)
img_rs_2 = cv2.resize(img_re_2, None, fx=1.5, fy=0.5)
cv2.imshow('Image', img_rs_2)
cv2.waitKey()

次に倍率を指定してサイズ変更します。「cv2.resize(img_re_2, None, fx=1.5, fy=0.5)」の「fx=1.5, fy=0.5」部分でx方向、y方向の倍率を指定します。その際は1件目で指定した画像サイズは「None」と指定します。

画像の拡大・縮小②

平行移動同様にアフィン変換で拡大・縮小をすることもできます。こちらも理解しやすいように拡大量の部分を抜き出しておきました。

img = cv2.imread('./Sample.jpg', 0)
x, y = 2, 1
M = np.float32([[x, 0, 0],
                 [0, y, 0]])
img_s = cv2.warpAffine(img, M, (480, 360))
cv2.imshow('Image', img_s)
cv2.waitKey()

画像の変換

元の画像からデータを抜き出したり、変換することにより解析の対象となる特徴量を抜き出だすことにより解析ができるようにします。

二値化

閾値を決め、その閾値に従って画像を白と黒で表現します。画像を鮮明にしたり、単純にしたりすることができるので分析の際に多く使われます。

img = cv2.imread('./Sample.jpg' ,0)
thr, img_th = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)
cv2.imshow('Image', img_th)
cv2.waitKey()

「thr, img_th = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)」の部分で二値化を行っています。2変数が取り出され、1つ目、今回の場合は「thr」には閾値が入ります。2つ目、今回の場合は「img_th」に二値化されたデータが入ります。

引数は、前から順番に「入力する画像」「閾値(下限)」「閾値(上限)」「閾値指定方法」です。

試しに下限の閾値を200にすると黒くする範囲が増え、下のようになります。

最大値を下げると下のようになります。

img = cv2.imread('./Sample.jpg' ,0)
thr, img_th = cv2.threshold(img, 100, 255, cv2.THRESH_OTSU)
print(thr)
cv2.imshow('Image', img_th)
cv2.waitKey()

閾値を自動で設定するために、4つ目の閾値を「cv2.THRESH_OTSU」に変更しました。この場合、閾値は先ほどと同様に1つ目のデータとして出力されるので、確認で表示させました。閾値が127と出力されました。

エッジ抽出

画像の特徴をエッジで拾うことは多々あります。特に、何もないところに不良がでた跡や、物と物の境界を抽出することができるので、それを拾って機械学習することで画像検知をすることもあります。

img = cv2.imread('./Sample.jpg', 0)
img_e = cv2.Canny(img, 100, 100)
cv2.imshow('Image', img_e)
cv2.waitKey()

エッジ検出については以下の記事でわかりやすく解説しています。

エッジ検出を完全理解!主要3フィルタとCanny法の実装手順を解説エッジ検出の仕組みやCanny法をOpenCVで実装する手順を紹介します。本記事では、エッジ検出の数学的な理論やアルゴリズムを理解したうえで、正しい実装方法や主要な3つのフィルタ(ガウシアンフィルタ、ソーベルフィルタ、ラプラシアンフィルタ)を学べます。エッジ検出を自力で実装したい方は、必見です。...

閾値処理

同様に閾値での抽出も比較的簡単に実施することができます。

img = cv2.imread('./Sample.jpg', 0)
ret, img_bin = cv2.threshold(img, 120, 255, cv2.THRESH_BINARY)
cv2.imshow('Image', img_bin)
cv2.waitKey()

デノイズ

ノイズ除去を行います。機械学習で学習させるデータは、特徴がはっきり出ているデータのほうが精度が上がる傾向にあるので、ノイズが邪魔になっている場合はデノイズします。

img = cv2.imread('./Sample.jpg', 0)
img_dn = cv2.fastNlMeansDenoising(img, h=20)
cv2.imshow('Image', img_dn)
cv2.waitKey()

今回の場合は毛をノイズ認識してのっぺりした画像になってしまいましたが、ノイズを除去して特徴部分に注目できます。

ブラー

全体をぼかす処理としてブラーがあります。ぼかされるので、汎化能力が向上する場合があります。

img = cv2.imread('./Sample.jpg', 0)
img_b = cv2.blur(img,(10,10))
cv2.imshow('Image', img_b)
cv2.waitKey()

カスケード型分類機による画像認識

OpenCVで画像加工したのち、機械学習やニューラルネットワークで画像を分類することが多いと思いますが、OpenCV単体で学習済みモデルであるカスケード学習機を使用して画像認識をすることも可能です

OpenCVによる画像認識は多くの解説が出ているので、今回は極力簡素化して理解優先で確認していきたいと思います。

img_face = cv2.imread('./Sample_.jpg')
clf = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
faces = clf.detectMultiScale(img_face, 1.1, 3)

for (ex,ey,ew,eh) in faces:
    cv2.rectangle(img_face , (ex, ey), (ex+ew, ey+eh), (255, 255, 255), 2)

cv2.imshow('Image', img_face)
cv2.waitKey()

この中で、実際に解析にかかわっているのは2行目と3行目のみです。非常に簡単ですね。では1行ずつ内容を見てみましょう。

img_face = cv2.imread('./Sample_.jpg')

1行目:これはいままでの部分でも出てきましたが、画像を読み込んでいるだけですね。

clf = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')

2行目:モデルを読み込んでいます。今回は顔認識用のモデルとして「haarcascade_frontalface_alt.xml」を使用しています。モデルはgithubから取得可能です。すでに学習済みのものをダウンロードして使うことができるわけですね。

faces = clf.detectMultiScale(img_face, 1.1, 3)

3行目:先ほど読み込んだモデルで解析を行います。結果は下記のように数値で保存されています。解析自体は2行目と3行目だけで実施しています。

for (ex,ey,ew,eh) in faces:
    cv2.rectangle(img_face , (ex, ey), (ex+ew, ey+eh), (255, 255, 255), 2)

4行目:先ほど出てきたエリアを画像に書き込んでいます。検出結果の数分だけ資格を書く処理をしています。

cv2.imshow('Image', img_face)
cv2.waitKey()

5,6行目:結果を表示しているだけです。

結果として下のような結果記入済みの画像が出力されました。

データサイエンスを学習するならTech Teacherで!

『Tech Teacher』3つの魅力

魅力1. オーダーメイドのカリキュラ

『Tech Teacher』では、決められたカリキュラムがなくオーダーメイドでカリキュラムを組んでいます。「質問だけしたい」「相談相手が欲しい」等のご要望も実現できます。

    魅力2. 担当教師によるマンツーマン指導

    Tech Teacherでは完全マンツーマン指導で目標達成までサポートします。
    東京大学を始めとする難関大学の理系学生・院生・博士の教師がが1対1で、丁寧に指導しています。
    そのため、理解できない箇所は何度も分かるまで説明を受けることができます。

    魅力3. 3,960円/30分で必要な分だけ受講

    Tech Teacherでは、授業を受けた分だけ後払いの「従量課金制」を採用しているので、必要な分だけ授業を受講することができます。また、初期費用は入会金22,000円のみです一般的なプログラミングスクールとは異なり、多額な初期費用がかからないため、気軽に学習を始めることができます。

    まとめ

    ・魅力1. 担当教師によるマンツーマン指導

    ・魅力2. オーダーメイドのカリキュラム

    ・魅力3. 3,960円/30分で必要な分だけ受講

    質問のみのお問い合わせも受け付けております。

    まとめ

    冒頭にも書きましたが「Python + OpenCVで画像処理をマスター!使用法・実用例を解説」に概要があるので、データサイエンスをするときによく実施する内容を中心に、具体的なコードを書いてみました。OpenCVはよく利用するライブラリですが、コードをこまかく覚えておくことはないと思うので、このページをブックマークて処理をしたい内容を目次で探して活用いただければと思います。

    Python + OpenCVで画像処理をマスター!使用法・実用例を解説Python初心者の方でOpenCVの使い方について悩んでいる人必見。OpenCVの基礎知識やインストール方法、使い方を網羅しました。OpenCVを使用した画像動画処理について悩んでいる人は参考にしてください。...