叉焼.log

札幌のこととか、ITの事とか

【ラズパイ3】ラズパイカメラでライントレースする

またもはてなさんから記事をかけと怒られたので書きます。
秋葉原で衝動買いしたラズパイカメラの話です。

プロローグ

私はロボット系のサークルに入っているのですがそのサークル内で部員対抗ライントレースロボット大会をやろうという話になりました。ライントレースロボットというのは地面にテープで貼ったラインに沿うように自立して動くロボット(多くは車型)のことです。そしてそのロボットがスタートからゴールするまでの時間を競うのがライントレースロボット大会というわけです。このライントレースロボはフォトリフレクタという素子を使うのが一般的らしいのですが、私は調子に乗ってラズパイのカメラを使ってやってみようということになりました。イメージ的にはこんな感じです。
f:id:cha-shu00:20170808091655j:plain
ライントレースロボットはラインの上を走れば良いので決して2階立てになったり、ましてやその上にiPhoneが乗ったりすることはないのですが私は調子乗りなので(ry
以上が夏休み直前の出来事です。

picameraモジュールを使う

ラズパイカメラを買うとついついそれで写真を撮りたくなります。家に押しかけてきた友人や部員をひたすら撮影して遊んだ後はいよいよ実装に移ります。ラインをカメラで読み取るだけなのでopenCVなどの高度なライブラリは必要ありません。pythonで記述できるpicameraというモジュールがあるのでそちらを使います。イメージはこんな感じ。

line_trace.py
from picamera.array import PiYUVAnalysis
import picamera
import time

resol_x = 64
resol_y = 48
class MyAnalysis(PiYUVAnalysis):
    def __init__(self, camera):
        super().__init__(camera)

    def analyse(self, array):
        self.array = array
        self.imgary = [int(self.array[resol_y/2,2*i,0]) for i in range(0, int(resol_x/2))]
        #以下、読み取った値に応じて処理

with picamera.PiCamera() as camera:
    #カメラの解像度
    camera.resolution = (resol_x, resol_y)
    #フレームレート
    camera.framerate = 7
    output = MyAnalysis(camera)
    camera.start_recording(output, format="yuv")
    time.sleep(0.1)
    try:
        camera.wait_recording(10000)
    
    except:
        pass

picameraのanalyzeメソッドがとても便利でした。このメソッドは1秒間に指定されたフレームレートの回数だけ、カメラから画像を読み取り実行されます。よみとった画像は[y座標,x座標,yuvのいずれか]という3次元配列として渡されるのでこれを使って処理します。特にyuvというフォーマットのyは輝度を表すので、この値を使いラインの有無を判定します。このほかの部分はiPhoneと通信したり、GPIOピン制御をしたりといったカメラとは関係ない部分なので省きます。

一応完成品

f:id:cha-shu00:20170808102020j:plain
カメラとラインとの間に距離があるため、自然光や影の影響を受けやすいということもあり、上にはiPhoneを載せて内蔵の強力なライトで照らしています。iPhoneをライトがわりだけに使うのはさすがに故ジョブズ氏に飛び蹴りされても文句は言えないため、ちゃんとiPhoneのアプリも作成しました。また時間があればその辺りも記事にしようと思います。