NISHIO Hirokazu's website > NISHIO HIROKAZU # Archived COREBlog
これは2004年11月4日から2006年2月18日までZopeで運用していたCOREBlogの静的なアーカイブです。 新しい日記は「西尾泰和の日記」で運用しています。

PythonでUSBカメラから読み取り

明日から研究室旅行なのでサタデーハッキング(何故)

VideoCapture をダウンロードして、DLLsの中身とLibの中身をそれぞれPythonのインストールフォルダの下の同名フォルダの中にコピー。

>>> import VideoCapture
>>> cam = VideoCapture.Device()
>>> cam.getImage()
<PIL.Image.Image instance at 0x00C1AD28>
>>> _.save("c:\\cam.png", "PNG")
うわお。保存できてる。簡単すぎ!

getImageで帰ってきた値はPython Imaging LibraryのImageクラスのインスタンス。 早速ドキュメントを読もうかと思ったけど、dirしてみたらgetpixelっていう名前のメソッドがあったからそれを使ってみる。

>>> image.getpixel((0,0))
(45, 45, 0)
きっとRGBの値が取れているんだろう。 ドキュメントを読んでみると
im.getpixel(xy) => value or tuple

Returns the pixel at the given position. If the image is a multi-layer image, this method returns a tuple.

Note that this method is rather slow; if you need to process larger parts of an image from Python, use the getdata method.

と書いてあるのでimage.getdata()[0]とやってみたら同じく(45, 45, 0)が帰ってきた。想像通り。 じゃぁ直前の画像と差分を取るプログラムを書いてみよう。

これはカメラを帽子のつばにつけて、僕の目の辺りを撮影した画像の「直前の画像との差分」です。ピークが立ち上がっているところはまばたきだろうと思われます。時間解像度の関係でまばたきの間隔を正確に求めるのは難しそうだね。あと、目がちゃんと映る位置にカメラをセットしたけども、眼球移動じゃなくてまばたきを測定したいのだから目じゃなくてまぶたの辺りを撮影したほうがいいのかも。

「こんなとこ動かないかな」ってところを選んでみたら、まばたきのピークがすごくわかりやすくなりました。というかまばたきしていないときの変動がほとんどなくなりましたね。やっぱり目を写していたときは眼球の移動を拾ってしまっていたんですね。

逆に言えばまぶたと眼球が両方写るようにしてちょっと細工すればまばたきの頻度と同時に眼球移動だけの頻度も測定できるかも。

ソースコード。

import VideoCapture
class CameraDiff:
    def __init__(self):
        self.cam = VideoCapture.Device()
        self.cam.setResolution(352, 288)
        image = self.cam.getImage()
        self.prevData = image.getdata()

    def test(self):
        image = self.cam.getImage()
        image.show()

    def start(self):
        import time
        fo = open("c:\\mabataki.txt", "w")
        for i in range(100):
            fo.write("%d\n" % self.capture())
            time.sleep(0.05)
        fo.close()
        print "ok."

    def capture(self):
        curData = self.cam.getImage().getdata()
        sum = 0
        for i in range(len(curData)):
            u = curData[i]
            v = self.prevData[i]
            sum += ((u[0] - v[0]) ** 2 +
                    (u[1] - v[1]) ** 2 +
                    (u[2] - v[2]) ** 2)
        self.prevData = curData
        return sum

    def __del__(self):
        del self.cam

ちなみに__del__を実装したのは理由がある。 カメラのLEDがついている状態で新たにカメラにアクセスしようとするとハングアップしてしまう。おそらく一つのカメラには一度に一つの接続しか出来ないとかそういう制約があるんだろうと思う。でself.camを明示的にdeleteしないと、時々カメラのLEDがつきっぱなしになってしまう。きっとGCのタイミングが関係しているんだろう。GCが起きるまで悠長に待っているのも馬鹿らしいのでdelしてみた、というわけ。もしかしたらカメラオブジェクトにcloseメソッドとかがあるかもしれないけどdelしたらLEDが消えたのでそれでいいってことにしてみた。

あと、今は静止画キャプチャを繰り返しているけど、もしかしたら動画で取ればもっとフレームレートが上がったりするのかもしれない。これも気が向いたら調べてみよう。

あ、そうだ、この実験は天井にわんさか光源のある研究室で行ったのだけど、近くに光源があったり光源の位置に偏りがあるような環境では顔の向きによって撮影している部分の照らされ具合が大きく変化してまばたきどころじゃない可能性もあるね。難しい問題だけど、画素の平均値を取ってそれを引いてやれば全体的に明るくなったり暗くなったした場合の影響を減らせるかもしれない。あとは画像を高次元のベクトルだとみなしてPCAを掛けてやれば「全体的な照明の変化」軸と「まばたき」軸の2軸に分かれるだろうからそれで判別するとかだな。あー、いや、目を開けた状態と閉じた状態で頭を回してそれぞれを学習データとして判別分析とか。k近傍で十分いけそう。問題はあれだなー。どこまでPythonの計算速度で耐えられるかだw


[Python]  @2005-10-08 20:17
<< I18n続き | Main | org/gnu/readline/ReadlineLibrary >>

Comments このページは静的なアーカイブなので新しいコメントは受け付けておりません。ご意見ご感想はお気軽にメールでどうぞ。coreblog「あっとまーく」nishiohirokazu.org。
Trackbacks

PageView: 313 Score: 132.26485 このカウンタは2006-03-26 11:05で停止しています。
Powered by COREBlog

NISHIO Hirokazu's website > NISHIO HIROKAZU # Archived COREBlog
Contact me: coreblog"at mark"nishiohirokazu.org
Access counter: This Page:713094 Total:1827806 during 2004/01/23-2006/03/26