画像解析 opencv python入門

  • 19
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

macに以下をインストール

brew update
brew install -v cmake
brew tap homebrew/science
brew install opencv
export PYTHONPATH="/usr/local/lib/python2.7/site-packages/:$PYTHONPATH"

画像を取り込み表示する

適当にメッシの画像を撮ってきて「messi.jpeg」で保存
messi5.jpeg

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np
import cv2


# 元の画像を読み込む
img = cv2.imread('messi.jpeg',cv2.IMREAD_UNCHANGED)
# ウィンドウに表示
cv2.imshow("result", img)
# 書き出し
cv2.imwrite('img.jpg', img)
# 終了処理
cv2.waitKey(0)
cv2.destroyAllWindows()

終わらなかったら、control + z で強制終了

グレースケールにする

gray_img = cv2.imread('messi.jpeg', cv2.IMREAD_GRAYSCALE)
cv2.imshow("result", gray_img)

gray_messi.png

輪郭だけにする

canny_img = cv2.Canny(gray_img, 50, 110)
cv2.imshow("result", canny_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

canny_messi.png
```

輪郭の強さを変える

cv2.Canny()はキャニー法という方法で処理をする関数で、2つの閾値を設定します。数値を上げると書かれる輪郭は少なくなります。
詳しくはこちら http://postd.cc/image-processing-101/

canny_img = cv2.Canny(gray_img, 200, 400)

canny_img.jpg

ボールを検出する

対象となる物体が線や円などの標準的な形態であれば、ハフ変換というのを使って検出できます

circles = cv2.HoughCircles(canny_img, cv2.cv.CV_HOUGH_GRADIENT,
          dp=2, minDist=50, param1=20, param2=30,
          minRadius=5, maxRadius=20 )
print circles
import matplotlib.pyplot as plt
plt.imshow(canny_img)
plt.show()

パラメータ

dp ・・・ 処理するときに元画像の解像度を落として検出する場合は増やす。例えば、1だとそのままの画質で処理して、2だと1/2に縮小して処理するらしい。
minDist ・・・ 検出される円と円の最小距離
param1 ・・・ 「Cannyのエッジ検出器で用いる二つのしきい値の高い方」らしい。低いほどいろんなエッジを検出する
param2 ・・・ 中心検出計算時のしきい値。低いほど円じゃないものも検出する
minRadius ・・・ 最小半径
maxRadius ・・・ 最大半径

すると、5つ候補が出てきた [x,y,半径]

[[[ 125.           51.           16.27882004]
  [ 193.          161.            5.83095169]
  [ 131.          155.            8.24621105]
  [  71.           73.           18.02775574]
  [ 161.           91.           17.80449295]]]

円を元画像にプロット

cups_circles = np.copy(img)

if circles is not None and len(circles) > 0:
    circles = circles[0]
    for (x, y, r) in circles:
        x, y, r = int(x), int(y), int(r)
        cv2.circle(cups_circles, (x, y), r, (255, 255, 0), 4)
    plt.imshow(cv2.cvtColor(cups_circles, cv2.COLOR_BGR2RGB))
    plt.show()

print('number of circles detected: %d' % len(circles[0]))

figure_1.png

ほう、、、あってるけど、なんか変なのもカウントされている

パラメータなどを調整すると顔とボールだけにできた
(グレースケールをやめたらいい感じになった)
figure_1.png

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import cv2
import matplotlib.pyplot as plt

img = cv2.imread('messi5.jpeg',cv2.IMREAD_UNCHANGED)
canny_img = cv2.Canny(img, 230, 500)


# find hough circles
circles = cv2.HoughCircles(canny_img, cv2.cv.CV_HOUGH_GRADIENT,
          dp=2, minDist=100, param1=25, param2=30,
          minRadius=5, maxRadius=20 )
print circles

cups_circles = np.copy(img)

# if circles are detected, draw them
if circles is not None and len(circles) > 0:
    # note: cv2.HoughCircles returns circles nested in an array.
    # the OpenCV documentation does not explain this return value format
    circles = circles[0]
    for (x, y, r) in circles:
        x, y, r = int(x), int(y), int(r)
        cv2.circle(cups_circles, (x, y), r, (255, 255, 0), 4)
    plt.imshow(cv2.cvtColor(cups_circles, cv2.COLOR_BGR2RGB))
    plt.show()

cv2.waitKey(0)
cv2.destroyAllWindows()

ほう。色のフィスタをかけるともっと綺麗みたい
http://stackoverflow.com/questions/22870948/how-can-i-pythonically-us-opencv-to-find-a-a-basketball-in-an-image
http://www.pyimagesearch.com/2015/09/14/ball-tracking-with-opencv/

もしアプリ化をするなら参考になりそう
http://www.melt.kyutech.ac.jp/2015/onoue.pdf#search='opencv+ball+%E7%B2%BE%E5%BA%A6'

なんと、ラズパイで、追っかけカメラが作れるのか!
https://www.youtube.com/watch?v=58xxn6d_bUg

次は、動画チュートリアルをやってみる
http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_gui/py_video_display/py_video_display.html