ラズパイ× tensorflowでプラレール自動運転(2) 学習用の写真を撮りまくる
tensorflowで駅の写真を学習・推論させ、プラレールをラズパイで自動運転する第2回!学習用の写真を撮るプログラムを2種類、作成しました。
1.どんな写真を学習させたらいいか
カメラを取り付けた様子がこちら。
写真を撮ると、こんな感じ。
背景に写っている物を誤認識されたくないので、駅が映り込む右下1/4の部分のみトリミングして取り込むことにする(←精度向上のためコレが大事でした!)。
2.走りながら写真を撮るプログラム
import tkinter as tk import picamera, time, shutil import RPi.GPIO as GPIO from PIL import Image # 写真ファイル名の連番スタート値を設定 count_0 = 0 # 使用するピン番号を設定(MAX14870) GPIO.setmode(GPIO.BOARD) DIR_1 = 18 DIR_2 = 22 EN_N = 29 PWM1 = 32 PWM2 = 33 # 各ピンを出力ピンに設定 GPIO.setup(DIR_1, GPIO.OUT, initial=GPIO.LOW) # LOW:forward GPIO.setup(DIR_2, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(EN_N, GPIO.OUT, initial=GPIO.LOW) # Low active GPIO.setup(PWM1, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(PWM2, GPIO.OUT, initial=GPIO.LOW) p1 = GPIO.PWM(PWM1, 3000) p2 = GPIO.PWM(PWM2, 3000) p1.start(0) p2.start(0) p1.ChangeDutyCycle(6) p2.ChangeDutyCycle(6) try: while (1): with picamera.PiCamera() as camera: count_0 += 1 camera.resolution = (640, 480) camera.rotation = 180 # カメラが上下反対なので反転する #camera.start_preview() time.sleep(0.2) #camera.stop_preview() camera.capture("pic_" + str(count_0) + '.jpg') # 右下1/4部分のみトリミングする im = Image.open('/home/pi/Desktop/pic_' + str(count_0) + '.jpg') im_crop = im.crop((320, 240, 640, 480)) im_crop.save('/home/pi/Desktop/pic_' + str(count_0) + '.jpg', quality=95) filename = 'pic_' + str(count_0) + '.jpg' source = r'/home/pi/Desktop/'+filename destination = r'/home/pi/Desktop/case0/'+filename shutil.move(source, destination) except KeyboardInterrupt: # PWM を停止 p1.stop() p2.stop()
- PWMのDuty比は6という小さな値でゆっくり走らせる。
- 右下1/4をトリミングした後、デスクトップにある「case0」フォルダに移動させる。
- 写真を撮るごとに変数count_0がインクリメントされ、ファイル名の連番になる。
- 動作を止めるには「Ctrl + C」
というプログラムです。 また、駅が映り込んだ瞬間のデータを増やすべく止まって撮るバージョンがこちら。
import tkinter as tk import picamera, time, shutil from PIL import Image count_0 = 0 count_1 = 0 count_2 = 0 class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) # ウィンドウの設定 self.master.title("gather picture") self.pack() self.create_widget() def create_widget(self): self.label1 = tk.Label(self,text="3 case") self.label1.pack() def button0_click(): # button0をクリックした時の処理 with picamera.PiCamera() as camera: global count_0 count_0 += 1 camera.resolution = (640, 480) camera.rotation = 180 camera.start_preview() time.sleep(1) camera.stop_preview() camera.capture("pic_0" + str(count_0) + '.jpg') im = Image.open('/home/pi/Desktop/pic_0' + str(count_0) + '.jpg') im_crop = im.crop((320, 240, 640, 480)) im_crop.save('/home/pi/Desktop/pic_0' + str(count_0) + '.jpg', quality=95) filename = 'pic_0' + str(count_0) + '.jpg' source = r'/home/pi/Desktop/'+filename destination = r'/home/pi/Desktop/case0/'+filename shutil.move(source, destination) def button1_click(): # button1をクリックした時の処理 with picamera.PiCamera() as camera: global count_1 count_1 += 1 camera.resolution = (640, 480) camera.rotation = 180 camera.start_preview() time.sleep(1) camera.stop_preview() camera.capture("pic_1" + str(count_1) + '.jpg') im = Image.open('/home/pi/Desktop/pic_1' + str(count_1) + '.jpg') im_crop = im.crop((320, 240, 640, 480)) im_crop.save('/home/pi/Desktop/pic_1' + str(count_1) + '.jpg', quality=95) filename = 'pic_1' + str(count_1) + '.jpg' source = r'/home/pi/Desktop/'+filename destination = r'/home/pi/Desktop/case1/'+filename shutil.move(source, destination) def button2_click(): # button2をクリックした時の処理 with picamera.PiCamera() as camera: global count_2 count_2 += 1 camera.resolution = (640, 480) camera.rotation = 180 camera.start_preview() time.sleep(1) camera.stop_preview() camera.capture("pic_2" + str(count_2) + '.jpg') im = Image.open('/home/pi/Desktop/pic_2' + str(count_2) + '.jpg') im_crop = im.crop((320, 240, 640, 480)) im_crop.save('/home/pi/Desktop/pic_2' + str(count_2) + '.jpg', quality=95) filename = 'pic_2' + str(count_2) + '.jpg' source = r'/home/pi/Desktop/'+filename destination = r'/home/pi/Desktop/case2/'+filename shutil.move(source, destination) self.button0 = tk.Button(self,text="case 0", command=button0_click, width=30, heigh=3) self.button0.pack() # button0ウィジェット配置 self.button1 = tk.Button(self,text="case 1", command=button1_click, width=30, heigh=3) self.button1.pack() # button1ウィジェット配置 self.button2 = tk.Button(self,text="case 2", command=button2_click, width=30, heigh=3) self.button2.pack() # button2ウィジェット配置 if __name__ == "__main__": root = tk.Tk() app = Application(master=root) app.mainloop()
- 3つのボタンを配置し、分類させたいケースに合わせて格納フォルダを分けられる。
- 撮った瞬間に1秒だけプレビューを表示する。
- 各フォルダに格納時、右下1/4をトリミングする。
- 写真を撮るごとに変数count_0がインクリメントされ、ファイル名の連番になる。
実行時の様子がこちら。
ケースを分けられるようにしたのは、前方に他の車両がいて減速させるケースなどの実装も見込んでのことですが、駅があるときの停車だけを考える今回は、駅があるとき・ないときをそれぞれ20~30ずつ集めました。
では学習させてラズパイで実行(推論)してみよー。