サンプルコード配布:
https://github.com/tokyo-scipy/archive/tree/master/004/yasutomo57jp




 画像処理でのPythonの利用

                       @yasutomo57jp

             2012/06/16 Tokyo.Scipy #4
自己紹介
名前:川西康友
所属:京都大学学術情報メディアセンター

Python歴:1年くらい
  去年,RubyからPythonへ乗り換え
   OpenCVの公式サポートがないのが痛い
   Numpyと比べてNumerical Ruby使ってる人は少な
   かった…
  普段はPython又はC++でプログラミングしていま
  す


  こうして喋ってますがPython初心者です
自己紹介
何をやっている人か:研究してます
 映像メディアに対する認識など
  映像中の人物検出・追跡・照合
   o   最近ホットな防犯ネタ
  映像からのプライバシ情報の除去
Contents
入門編:画像処理にPythonを使う
 画像処理ライブラリの紹介
 簡単な画像処理の例
応用編:Numpy/Scipyを使った応用例
 固有空間を用いた物体領域抽出
入門編:画像処理にPythonを使
う
画像を簡単に処理したい
さらさらっと書いて即実行したい
色んな環境で動くプログラムを作りたい
C++とか使いたくない
画像処理まわりのPython
PIL(Python Imaging Library)
    http://www.pythonware.com/library/pil/handbook/index.htm

OpenCV
    http://docs.opencv.org/

scipy.ndimage
    http://docs.scipy.org/doc/scipy/reference/ndimage.html



画像を扱うライブラリが充実してきた
PIL : Python Imaging Library
インストール: $ easy_install pil

一番手っ取り早く“画像処理”が出来る
  画像の読み書き
  フォーマット変換
  サイズ,解像度変換
  各種フィルタ処理
  図形の描画
PIL プログラム例
画像を読み込んでエッジ検出して
回転させて表示して保存
import Image
import ImageFilter

img = Image.open(“lena.jpg”)

eimg = img.filter(ImageFilter.FIND_EDGES)

reimg = eimg.rotate(45)

reimg.show()

reimg.save(“lena_edge.jpg”)
OpenCV
インストール:      http://opencv.jp/download
 Ubuntuなら
 sudo apt-get install python-opencv

高度な処理が可能!
 カメラからの入出力
 様々な特徴抽出
 顔認識
 画像処理研究者の多くが利用
    (C++での利用が主だと思うが)
 画像は numpy.array 形式で扱う
   shape=(高さ,幅,チャンネル数),
   dtype=numpy.uint8 です
OpenCV プログラム例
  SURF特徴を取り出し,それを基に対応付け

import cv2

img1 = Image.open(“lena.jpg”)
img2 = Image.open(“lena_rotate.jpg”)

surfdetect = cv2.FeatureDetector_create(“SURF”)
surfextract = cv2.DescriptorExtractor_create(“SURF”)

keys1 = surfdetect.detect(img1)
keys2 = surfdetect.detect(img2)
keys1, features1 = surfextract.compute(img1, keys1)
keys2, features2 = surfextract.compute(img2, keys2)
OpenCV プログラム例
  SURF特徴を取り出し,それを基に対応付け

(続き)
# 対応点を探索
dm = cv2.DescriptorMatcher_create(“BruteForce”)
match = dm.match(features1,features2)
# ↑対応する特徴点のインデックスの組みが入っている

# あとは頑張って可視化(省略)
# C++なら cv::drawMatchesという関数があるが
# Pythonでは見つけられなかった…
# 今後実装されるのかも
cv2.imshow(“result”, result)
cv2.waitKey()
OpenCV プログラム例
  Haar-like特徴を使った顔検出
#!/usr/bin/env python

import cv2

cc = cv2.CascadeClassifier()
# 学習済みの識別器データを読み込み
cc.load("haarcascade_frontalface_alt.xml"):

img=cv2.imread("lena.jpg")
# 顔検出
faces = cc.detectMultiScale(img, 1.1)

#あとはfacesを画像に描画すればOK
Scipy.ndimage
インストール: $ easy_install scipy

使ったことないですが…
  各種フィルタ処理
  ヒストグラム計算
  モルフォロジ処理

  どうやら内部でPILを呼んでいるようです
Scipy.ndimage プログラム例
略
PILとNumpyの相互変換
PIL -> Numpy
  nimg = numpy.asarray(pimg)


Numpy -> PIL
  pimg = Image.fromarray(nimg)



これで PIL/numpy/scipy/OpenCV の関数
が自由に利用できる!
ちょっとScipy感が足りない…ので

応用編:
Numpy/Scipyを使った応用例
物体領域抽出
領域抽出はあらゆる画像処理の基本!
 処理対象を画像中から見つける

背景差分法


        -              =



観測画像         背景画像            差分画像

              画像はPETS 2001 dataset 3のものです
固有空間を用いたモデル化による手法
                    観測画像




           主成分分析    背景固有空間



           背景の変化を   推定した背景画像
           モデル化
     ・・・




時間
基本的な主成分分析の計算方法
各画像(n枚)を1つのベクトル(d次元)にする
 ラスタスキャンを行う
d次元ベクトルの共分散行列(d×d次元)
を求める
共分散行列の固有値・固有ベクトルを求める



もしくはd次元ベクトルを並べた行列Xを
特異値分解しても同じ
                詳しくはPRML本12章
主成分分析のPython実装
主成分分析
 OpenCV
   cv2.PCACompute()
 scikit-learn
   sklearn.decomposition.PCA()


固有値・固有ベクトルの計算(を個別にやる場合)
 numpy.linalg.eig()
 scipy.linalg.eig()
 注意点:教科書的にはデータxは列ベクトルだけど,
     プログラム的には行ベクトルで扱う
OpenCV プログラム例
# 頑張って各行に画像を入れる (imgvec=numpy.reshape(img,1)を使用)
images = load_to_mat(filenames)

# PCAする(3次元空間へ)
mean, eigenvectors =
  cv2.PCACompute( images, maxComponents=3)

# 背景を推定したい画像
img = cv2.imread(“input.bmp”)

# 固有空間へ投影
vec = cv2.project(img, mean, eigenvectors)

# 画像を復元
bgimg=cv2.backProject(vec, mean, eigenvectors)

        あとは img と bgimg を引き算すればOK
行列がでかすぎて無理と言われます
画像は100万画素→300万次元のベクトル
 共分散行列は300万^2の大きさに…
 計算がメモリ上で不可能になってくる

共分散行列を計算しなくてもいいやり方
 Dual PCA とか Kernel PCA
 画像枚数^2の大きさの行列を処理するだけ
Scikit-learn プログラム例
import sklearn.decomposition

# 線形カーネルでKernel PCA (たぶんDual PCAと同じ)
kpca = sklearn.decomposition.KernelPCA(kernel=“linear",
  fit_inverse_transform=True)

# 1行が1枚の画像になっている行列をもとに学習(とても時間がかかる)
kpca.transform(images)

# 背景を推定したい画像
img = cv2.imread(“input.bmp”).reshape(1)

# 固有空間へ投影
vec = kpca.transform(img)

# 画像を復元
bgimg = kpca.inverse_transform(vec)
物体領域の計算
 背景差分法


                  -                    =



    観測画像 img             背景画像 bimg          差分画像 result
# 画像同士の差を取る
diff = cv2.absdiff(img,bimg)
# しきい値以上の画素を選択
fgmask = diff < threshold
# 差分結果の画像を生成
result=numpy.zeros(img.shape[0:2], dtype=numpy.uint8)
result[ fgmask] = 255
まとめ
Pythonでも画像処理できる!
 もうPythonだけでいいやん!
 画像処理・認識を使ったWebサービス構築も
 楽々…のはず!

しかし…
 やっぱり遅い
 特にfor文使うと…
 スピードも欲しければCython使おう
       http://www.slideshare.net/lucidfrontier45/cython-intro
 あとPyCUDAとかPyOpenCLとか…

画像処理でのPythonの利用