Eine Kamerabrille, die einem querschnittsgelähmten Menschen per Eye-Tracking die Rollstuhlsteuerung ermöglicht. Durch die Bewegung der Augenlinse wird der Elektrorollstuhl in Blickrichtung gesteuert. Zum An- und Ausschalten befindet sich an den Griffen des Rollstuhls ein Taster, welcher von der Begleitperson bedient wird. Dieser Taster bewirkt das Starten und Stoppen des Rollstuhls. Die größte Schwierigkeit des Eye-Trackings sind unterschiedliche Lichtverhältnisse, daher ist zur Einstellung der Helligkeit ein Regler vorhanden. Dieser wird ebenfalls von der Begleitperson bedient.
• Raspberry Pi 3
• Raspicam
• DC Motoren
• 12V Batterie
• Powerbank
• Taster
• Potentiometer
• ADC
• Brille mit Kamerahalterung
• H-Brücke
import cv2 import numpy as np def get_position(x_value, brightness): cap = cv2.VideoCapture(0)#Bildquelle; bei RP normalerweise index 0 cap.set(11, 200)# kontrast while True: cap.set(10, brightness.value)#70 mittelwert, min 60, max 80 ret, frame = cap.read() #bildinformationen lesen if ret is False: break roi = frame[100:500, 170:850]#Bildausschnitt definieren #roi = frame[269: 795, 537: 1416] #zur Suche der Koordinaten, wird das Bild in schwarz/weiß umgewandelt rows, cols, _ = roi.shape gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) gray_roi = cv2.GaussianBlur(gray_roi, (7, 7), 0) #mit Hile von openCV koordinaten der Pupille ermitteln _, threshold = cv2.threshold(gray_roi, 3, 255, cv2.THRESH_BINARY_INV) contours,_ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True) for cnt in contours: (x, y, w, h) = cv2.boundingRect(cnt)#Koordinaten zur Weiterverarbeitung in einzelnen Variablen speichern x_value.value = int(x) #x koordinate der Pupille an die Steuerung uebergeben #zeichnen der vertikalen und horizontalen #cv2.drawContours(roi, [cnt], -1, (0, 0, 255), 3) cv2.rectangle(roi, (x, y), (x + w, y + h), (255, 0, 0), 2) cv2.line(roi, (x + int(w/2), 0), (x + int(w/2), rows), (0, 255, 0), 2) cv2.line(roi, (0, y + int(h/2)), (cols, y + int(h/2)), (0, 255, 0), 2) break #cv2.imshow("Threshold", threshold) #cv2.imshow("gray roi", gray_roi) cv2.imshow("Roi", roi) #anzeigen des Eyetrackings key = cv2.waitKey(30) if key == 27: break
import Eye_tracking as et import Taster from time import sleep import multiprocessing as mp from ctypes import c_bool import Rover import Poti import RPi.GPIO as GPIO try: x = mp.Value('i', 0) # x koordinate der Pupille taster_value = mp.Value(c_bool, False) #Ein/ Aus schalten der Motoren v = mp.Array('i', 2) # geschwindigkeit; index 0 = links/ index 1 = rechts brightness = mp.Value('i', 70) #initialisieren der Prozesse tracking = mp.Process(target=et.get_position, args=(x, brightness)) taster = mp.Process(target=Taster.switch_OnOff, args=(taster_value,)) rover = mp.Process(target=Rover.rover, args=(v,)) poti = mp.Process(target=Poti.get_value, args=(brightness,)) poti.start() tracking.start() taster.start() #Motoren mit v=0 starten v[0] = 0 v[1] = 0 rover.start() #"falsche" koordinaten mit maximalen x werten filtern #50 160 290 #max wert rechts: 50 #max wert links: 290 while True: while taster_value.value == True: #sobald start/stop-knopf gedrückt wurde, fahre los: if(x.value > 0 and x.value > 50 and x.value < 290): #Wenn Position der Pupille erkannt wird if(x.value < 140): #fahre nach rechts v[0] = 50 v[1] = 25 #print("rechts") elif(x.value > 180): # fahre nach links v[0] = 25 v[1] = 50 #print("links") elif(x.value > 140 and x.value < 180): #fahre geradeaus v[0] = 50 v[1] = 50 print("gerade") else:#anhalten wenn Pupille nicht erkannt wird v[0] = 0 v[1] = 0 #anhalten wenn start/stop-knopf betätigt wird v[0] = 0 v[1] = 0 except KeyboardInterrupt: print("Programm beenden..") poti.terminate() taster.terminate() tracking.terminate() rover.terminate() GPIO.cleanup()
import spidev from time import sleep import RPi.GPIO as gpio gpio.setmode(gpio.BCM) gpio.setup(18, gpio.OUT) gpio.output(18, gpio.HIGH) #stromversorgung des Potis spi = spidev.SpiDev() # SPI-Bus initialisieren spi.open(0,0) # SPI Bus 0, Client 0 oeffnen spi.max_speed_hz=1000000 # Max. Geschw. begrenzen fuer stabiles Auslesen def readMCP3008(channel):# auslesen des Signals auf entsprechendem Channel adc=spi.xfer2([1,(8+channel)<<4,0]) wert = ((adc[1]&3) << 8) + adc[2] return wert def get_value(value): while True: #frage zweimal pro Sekunde den Wert des Reglers ab v=readMCP3008(0) # A/D Wandler auf Channel 0 auslesen; v entspricht einer Zahl zwischen 0 und 1023 p = int((v/10.23)/5 + 60)# umrechnen in Prozent (v/1023/100) und umrechnung in Helligkeitswert zwischen 60 und 80 value.value = p #Helligkeitswert an Steuerung übergeben sleep (0.5)
Die Motoren werden per PWM gesteuert. Anleitungen dazu sind im Wiki vorhanden.
Die Methode erwartet ein Array v. v[0] = Geschwindigkeit linker Motor; v[1] = Geschwindigkeit rechter Motor
Im Array v ist der Wert für die Steuerung per PWM gespeichert.
Anleitungen für den Taster befinden sich ebenfalls im Wiki. Hierbei ist ein Pulldown Widerstand zu verwenden
Darüber hinaus sollte der Taster entprellt werden