A caterpillar that uses a Raspberry Pi 3b + and a Pi camera to classify photos taken with SVM into real-time "forward", "right turn", "left turn", and "backward".
Please see here because a picture is worth a thousand words. YouTube: Obstacle Avoidance Caterpillar Test Run Using Raspberry Pi
[Color illustration Learn electronic work with the latest Raspberry Pi Make and move to understand how it works (Blue Bucks)](https://www.amazon.co.jp/%E3%82%AB%E3%83%A9%E3% 83% BC% E5% 9B% B3% E8% A7% A3-Raspberry-Pi% E3% 81% A7% E5% AD% A6% E3% 81% B6% E9% 9B% BB% E5% AD% 90% E5% B7% A5% E4% BD% 9C-% E4% BD% 9C% E3% 81% A3% E3% 81% A6% E5% 8B% 95% E3% 81% 8B% E3% 81% 97% E3 % 81% A6% E3% 81% 97% E3% 81% 8F% E3% 81% BF% E3% 81% 8C% E3% 82% 8F% E3% 81% 8B% E3% 82% 8B-% E3% 83% 96% E3% 83% AB% E3% 83% BC% E3% 83% 90% E3% 83% 83% E3% 82% AF% E3% 82% B9 / dp / 4062579774 / ref = sr_1_3? __mk_ja_JP = % E3% 82% AB% E3% 82% BF% E3% 82% AB% E3% 83% 8A & keywords =% E3% 83% A9% E3% 82% BA% E3% 83% 99% E3% 83% AA% E3% 83% BC% E3% 83% 91% E3% 82% A4% E3% 81% A7% E5% AD% A6% E3% 81% B6% E9% 9B% BB% E5% AD% 90% E5% B7% A5% E4% BD% 9C & qid = 1561894984 & s = hobby & sr = 1-3-catcorr)
For hardware, see Chapter 10 + Just attach the Pi camera. For software, refer to Chapter 8 + Preprocessing + svm (Scikit-learn) + Image saving for re-learning
Hard: The camera only shoots in front of me. If the background is reflected, it seems that it can not be classified, so enter the image only in front of the caterpillar.
Software ①: Input to svm is 28x28 pixels / photo (grayscale)
The Pixel camera shot was reduced to 64x64 pixels (color) and preprocessed to 28x28 pixels (grayscale).
If the preprocessing takes time, there will be a time lag in the transmission to the motor. At this resolution, I didn't really notice the delay.
By the way, the 64x64 (color) image looks like this
28x28 (grayscale)
Software ②: I made a mode to run while collecting data for re-learning If SavePics is set to 1, the captured image is saved for re-learning while proceeding. The saved image moves forward while labeling the file name as to which of "forward", "right turn", "left turn", and "backward" was judged. After driving, people can easily relearn images with the wrong label by dividing them into folders and moving camera_car_preprocess.py. It takes about 3 minutes for pre-processing with about 200 sheets x 4 classification, and learning is completed in an instant, so it is easy to make adjustments locally.
Soft ③: Turn right when retreating If you go straight back, you will enter an infinite loop, so I try to turn to the right.
camera_car_preprocess.py
from PIL import Image
import numpy as np
import glob
from sklearn import svm, metrics
from sklearn.model_selection import train_test_split
import pickle
ModelName = "model_20191102_9.pickle"#As you wish.
def main():
Path = '/home/pi/document/camera_car/Train/'
Left_L = glob.glob(Path + '1_Left/*.jpg')
Right_L = glob.glob(Path + '2_Right/*.jpg')
Center_L = glob.glob(Path + '0_Center/*.jpg')
Back_L = glob.glob(Path + '3_Back/*.jpg')
X_L = Preprocess(Left_L)
Y_L = np.ones(int(len(X_L)/784))
X_R = Preprocess(Right_L)
Y_R = np.full(int(len(X_R)/784),2)
X_C = Preprocess(Center_L)
Y_C = np.zeros(int(len(X_C)/784))
X_B = Preprocess(Back_L)
Y_B = np.full(int(len(X_B)/784),3)
X = np.r_[X_L, X_R, X_C, X_B]#concatinate all preprocessed pics.All pre-processed photo combination
X = X.reshape([int(len(X)/784),784])#make array.Matrix
y = np.r_[Y_L, Y_R, Y_C, Y_B]#teacher data addition.Teacher data addition
print(X.shape)
print(y.shape)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=42)
clf = svm.SVC(kernel='linear')
clf.fit(X_train, y_train)
pre = clf.predict(X_test)
ac_score = metrics.accuracy_score(y_test, pre)
print(ac_score)#print score.Accuracy display
with open(ModelName, mode='wb') as fp:
pickle.dump(clf, fp)#save model.Model output
def Preprocess(files):
size = [28,28]
array = np.empty([size[0]*size[1],0],int)
print(array.shape)
print(files)
for i, file in enumerate(files):
img = Image.open(file).convert('L')
img = img.resize(size, Image.ANTIALIAS)
print(img.format, img.size, img.mode,img.getextrema())
img_arr = np.asarray(img)
print("OD"+str(img_arr.ravel().shape))
array = np.append(array,img_arr.ravel())
print(array.shape)
return array
if __name__ == '__main__':
main()
camera_car_main.py
# -*- coding: utf-8 -*-
from picamera import PiCamera
import RPi.GPIO as GPIO
from time import sleep
from PIL import Image
import numpy as np
import os
import glob
import pickle
import shutil
import random
def Preprocess(i,SaveP):
size = [28,28]
array = np.empty([size[0]*size[1],0],int)
print(array.shape)
FullPath = glob.glob('/home/pi/document/camera_car/Predict/*.jpg')
print(FullPath)
#Preprocessing
img = Image.open(FullPath[0]).convert('L')
img = img.resize(size, Image.ANTIALIAS)
print(img.format, img.size, img.mode,img.getextrema())
#Make one dimention array
img_arr = np.asarray(img)
print("OneDimention"+str(img_arr.ravel().shape))
if SaveP:
os.remove(FullPath[0])
else:#saving pics for re-training the model.Photo save for Dewa
shutil.move(FullPath[0],'/home/pi/document/camera_car/Predict/done/%s.jpg' % i)
return img_arr.ravel(), img
PickleName = "model_20191102_9.pickle"#indicate trained model(pickle)
SavePics = 0
with open(PickleName, mode='rb') as fp:
clf = pickle.load(fp)
camera = PiCamera()
#camera.rotation = 180#if camera is upside down If the camera is upside down
camera.resolution = (64,64)
GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(23, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
p0 = GPIO.PWM(25, 50)#RH
p1 = GPIO.PWM(24, 50)#RH
p2 = GPIO.PWM(23, 50)#LH
p3 = GPIO.PWM(22, 50)#LH
p0.start(0)
p1.start(0)
p2.start(0)
p3.start(0)
print("start moving...")
sleep(10)
i = 0
duty = 70
#At first go forward
p0.ChangeDutyCycle(20)
p1.ChangeDutyCycle(0)
p2.ChangeDutyCycle(20)
p3.ChangeDutyCycle(0)
try:
while True:
#Take a pic and save to indicated folder.Take a photo and save it in the specified folder
i += 1
camera.capture('/home/pi/document/camera_car/Predict/%s.jpg' % i)
#preprocessing at indicated folder.Preprocess photos in a specified folder
X_pred, img = Preprocess(i, SavePics)
#predict estimate
pred = clf.predict(X_pred)
#change duty ratio.Duty ratio change
if pred[0] == 0:#Advance
print("Forward")
p0.ChangeDutyCycle(duty)
p1.ChangeDutyCycle(0)
p2.ChangeDutyCycle(duty)
p3.ChangeDutyCycle(0)
sleep(0.8)
elif pred[0] == 1:#left turn left
print("Left")
p0.ChangeDutyCycle(duty-20)
p1.ChangeDutyCycle(0)
p2.ChangeDutyCycle(0)
p3.ChangeDutyCycle(20)
sleep(0.3)
elif pred[0] == 2:#right turn right
print("Right")
p0.ChangeDutyCycle(0)
p1.ChangeDutyCycle(20)
p2.ChangeDutyCycle(duty-20)
p3.ChangeDutyCycle(0)
sleep(0.3)
elif pred[0] == 3:#backward backward
p0.ChangeDutyCycle(0)
p1.ChangeDutyCycle(duty-10)
p2.ChangeDutyCycle(0)
p3.ChangeDutyCycle(duty-40)
print("Backing...")
sleep(1)
print("finish backing")
#save preprocessed pic Save preprocessed photo
if SavePics:
pass
else:#collect preprocessed pics with pred number.Save re-learning photo (with estimated value)
rand = random.randint(0,100000)
img.save('/home/pi/document/camera_car/Train/'
+str(i)+'_'+str(int(pred[0]))+
'_'+str(rand)+'.jpg')
except KeyboardInterrupt:
pass
p0.stop()
p1.stop()
GPIO.cleanup()
The folder structure is
│ camera_car_main.py │ camera_car_preprocess.py │ model_20191102_8_best.pickle │ model_20191102_9.pickle ├─Predict │ └─done └─Train ├─0_Center ├─1_Left ├─2_Right └─3_Back
Please. By the way, there are two pickles, but 8 was the best. 9 is a re-learning version of 8, but since it is not actually running, the ability is unknown.
It was interesting because I was able to think about various things from hardware to logic and implement it, and I learned about logic by thinking about re-learning. The improvement is that people have to annotate in order to relearn, so the drawback is that you can't relearn on the spot without a large display.
Recommended Posts