19番目の日記

情報系よわよわ高専生がやったことや思ったことをつらつらと.

PythonとOpenCVで画像解析②

 おはようこんにちはこんばんは。SIGMAです。今回はPythonOpenCVで画像解析、第二回です。前回1は前置きが長くなってしまってあまり書けなかったので今回からちょっと詳しく書いていこうかと!

 今回から僕が普段使っているこの画像を使いながらやっていきます。

f:id:sigma1425:20191226153815p:plain
ロボットにカメラをつけたらこれくらいかなといった角度でとった写真

 今のところの目標は、中央下にある白線をライントレースできるようにしたいなと。

画像の表示、保存

画像の表示

 画像の読み込みは前回の記事で書きましたがimread()を使います。では読み込んだ画像をどうやって表示するのかと言いますと、imshow()を使います。

import cv2

img_path = "./img/sample.png"
img = cv2.imread(img_path, -1)
cv2.imshow("image", img)
cv2.waitKey(0)

cv2.destroyAllWindows()

実行結果 f:id:sigma1425:20191226160156p:plain

 imshow()の第一引数にウインドウの名前、第二引数に表示したい画像のndarrayを渡します。ただimshowで表示するだけではすぐにプログラムが終了してしまうので、waitKey(0)でなにかキーが押されるまで待機します。2また、プログラムが終了すればウインドウは勝手に閉じるのですが、念のためdestroyAllWindows()で全てのウインドウを閉じてからプログラムを終了します。

画像の保存

 なにか画像をいじってその画像を新たに保存したいといった時にはimwrite()を使います。

import cv2

img_path = "./img/sample.png"
img = cv2.imread(img_path, -1)

gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite("./img/gry.png", gry)

実行結果 f:id:sigma1425:20191226162810p:plain  ここでは詳しく書きませんがcvtColor()で読み込んだ画像をグレースケールに変換して保存しました。imwrite()は第一引数に保存したい画像のパス、第二引数に保存したい画像のndarrayを渡します。imgというフォルダにgry.pngができていますね。

 ここまでが画像解析をする上でよく使うであろう基本的な処理です。
まとめると、

  • imread() - 画像の読み込み
  • imshow() - 画像の表示
  • imwrite() - 画像の保存
  • waitKey(0) - キーが入力されるまで待機

の4点です。基本的にimshow()とwaitKey(0)はセットで使うことが多いです。

画像の輪郭を抽出

 ここまでは画像解析というよりはPythonで画像を扱うための準備でした。ここから少し画像解析っぽいことをしていきます。まずは輪郭の抽出です。というのも、ライントレースを行うためには白線の輪郭を抽出し、その回帰直線の傾きを求める必要があるからです。
 輪郭の抽出にはCanny()を使います。次のコードをみてください。

import cv2

img_path = "./img/sample.png"
img_gry = cv2.imread(img_path, 0)

canny = cv2.Canny(img_gry, 100, 200)

cv2.imshow("canny", canny)
cv2.waitKey(0)

cv2.destroyAllWindows()

実行結果

f:id:sigma1425:20191226171727p:plain
なんか色々と輪郭が検出できてますね

 Canny()の第一引数に輪郭を抽出したい画像のndarray、第二第三引数には閾値を渡します。
 Cannyのアルゴリズムは詳しく話すと記事1つ2つ書けそうなのでまたの機会にしようかと思います。とりあえず今は閾値は小さい方をより小さくすると抽出する輪郭が増え、大きくすると減るんだなぁぐらいで覚えといてください。

まとめ

今回までにやったこととしては、

  • 画像の読み込み
  • 画像の表示
  • 画像の保存
  • 輪郭の抽出

の4点です。ただ輪郭を抽出するだけでは必要のない情報も含んでいますのでここからは必要な情報だけを抜き出すなどする必要があります。まだまだやることは多いですね。

 今回はここまでにしようかと!当面はライントレースができるようになることを目標にしますが、最終的な目標はライントレースと物体(ボトルフリップの時のテーブルやランランランドリーの時の物干し竿)を検知してロボットの自動制御が満足にできるようになることです。まだまだ道のりは遠いですね。果たしてオフシーズンの間に実現できるのでしょうか。
 ここまで読んでくれた方ありがとうございました。


  1. PythonとOpenCVで画像解析① - 19番目の日記

  2. waitKey()は引数に待機したい秒数をミリ秒単位で渡しますが、0を渡すことでなにかキーが押されるまで待機します。また、ここでは説明しませんが特定のキー入力のみを待つこともできます。