Hur till spår din Robot med OpenCV (11 / 28 steg)
Steg 11: Se upp alla ni som går in här
På baksidan, om du är en Python guru, eller yanno, bara en sassy-byxor: Känn dig fri att lägga till korrigeringar och kommentarer på denna sida. Jag skulle älska att göra denna kod växa genom kritik. Vet, jag garanterar följande: stavfel, grammatik problem, ologiska kodning, artefakter från felsökning och liknande. Men oroa dig inte, jag är tjock flådda och brukar bära min stora pojke trosor.
Jag hävda, skrevs den grundläggande koden för färg spårning av Birgitta Rahman i ett svar på Stack Overflow.
Dessutom har jag inkluderat koden som en bifogad fil, det är längst. Videospel söder.
1 | #Written av patos fylld hacka: C. Thomas Brittainimportcv2importnumpyasnpimportserialfromtimeimport sömn #For att få information från Arduino (tx togs av Target X: P) globala rx |
motorBusy = "Nej" #Holds frame indexglobal iFrame
iFrame = 0defOpenCV():
#Create videoinspelning
Cap = cv2. VideoCapture(0)
#Globalizing variablesglobal cxAvg #<---jag minns inte varför... globala cxFound
globala iFrame
globala intRx
globala rx
globala tranx
#Flag för att få ett nytt mål.
newTarget = "Ja" #Dot counter. Han är en hungrig flodhäst...
prickar = 0 #This innehar bot centroiden X & Y genomsnittet
cxAvg = 0
cyAvg = 0 #Stores gamla position för rörelsen bedömning.
xOld = 0
yOld = 0 #Clearing följetongen skicka sträng.
printRx = "" while(1):
#"printRx" är separat om jag vill #parse ut andra sensordata från bot
printRx =str(intRx)
#Bot rubrik, oförändrad
headingDeg = printRx
#Making det ett nummer så vi kan spela med den.
intHeadingDeg =int(headingDeg)
headingDeg =str(intHeadingDeg)
#Strings att hålla "Target låsstatus".
stringXOk = ""
stringYOk = "" #Incrementing frame index
iFrame = iFrame + 1 #Read ramar
_, ram = cap.read()
#Smooth det
ram = cv2.blur(frame,(3,3))
#Convert till hsv och hitta olika färger
HSV = cv2.cvtColor (ram, cv2. COLOR_BGR2HSV)
tröska = cv2.inRange (hsv,np.array ((0, 80, 80)),
/ np.array ((20, 255, 255)))
thresh2 = thresh.copy()
#Find konturer i tröskeln bilden
konturer, hierarki = cv2.findContours
(tröska, cv2. RETR_LIST, cv2. CHAIN_APPROX_SIMPLE)
#Finding kontur med maximal areal och lagrar det som best_cnt
max_area = 0for cnt i konturer:
Area = cv2.contourArea(cnt)
om området > max_area:
max_area = område
best_cnt = cnt
#Finding centroids best_cnt och rita en cirkel där
M = cv2.moments(best_cnt)
CX, cy = int(M['m10']/M['m00']), int(M['m01']/M['m00'])
CV2.Circle(Frame,(CX,CY),10,255,-1)
#After 150 ramar, jämför bot X och X genomsnitt, #if är de samma + eller - 5, det förutsätter bot är att tracked.if iFrame > = 150:
om cxAvg < (cx + 5) och cxAvg > (cx -5):
xOld == cxAvg
stringXOk = "X Lock" om cyAvg < (cy + 5) och cyAvg > (cy -5):
yOld == cyAvg
stringYOk = "Y Lock" #This är att hitta medelvärdet av X cordinate. Används för att fastställa #a visuell länk med robot. #X
cxAvg = cxAvg + cx
cxAvg = cxAvg /2 #Y
cyAvg = cyAvg + cy
cyAvg = cyAvg /2 #//Finding Target vinkel / / / #Target cordinates. #Randomizing target.if newTarget == "Ja":
tX = random.randrange (200, 400, 1)
tY = random.randrange (150, 350, 1)
newTarget = "Nej" om iFrame > = 170:
om tX > cxAvg-45and tX < cxAvg + 45:
Skriv ut "Gjort det genom X" om tY > cyAvg-45and tY < cyAvg + 45:
Print "Gjort det genom Y"
newTarget = "Ja"
prickar = prickar + 1 #Slope
DX = cxAvg - tX
dy = cyAvg - tY
#Quad jag--Goodif tX > = cxAvg och tY < = cyAvg:
rads = atan2(dy,dx)
degs = degrees(rads)
degs = degs -90 #Quad II--Goodelif tX > = cxAvg och tY > = cyAvg:
rads = atan2(dx,dy)
degs = degrees(rads)
degs = (degs * -1)
#Quad IIIelif tX < = cxAvg och tY > = cyAvg:
rads = atan2(dx,-dy)
degs = degrees(rads)
degs = degs +180 #degs = 3elif tX < = cxAvg och tY < = cyAvg:
rads = atan2(dx,-dy)
degs = degrees(rads) +180 #degs = 4 #Convert float till int
targetDegs =int(math.floor(degs))
#Variable att skriva ut grader offset från målet vinkel.
strTargetDegs = "" #Put målet vinkel till en sträng som skrivas ut.
strTargetDegs =str(math.floor(degs))
#///End att hitta målet vinkel / / / #/ / / flytta Bot ///#Don't börja flytta tills saker och ting ready.if iFrame > = 160:
#This jämför den bot rubrik med målet vinkel. Det måste #be +-30 för bot att gå framåt, annars kommer det turn.if intHeadingDeg < = (targetDegs + 30) och intHeadingDeg > + (targetDegs -30):
tranx = 3
motorDuration = 10 #I ska använda senare #Forwardelse:
om intHeadingDeg < targetDegs:
IF1 < (targetDegs - intHeadingDeg):
#abs (intHeadingDeg - targetDegs) > = 180:
tranx = 2
motorDuration = 10print (intHeadingDeg - targetDegs)
skriva ut "Rätt 1" elif1 > (targetDegs - intHeadingDeg):
#abs (intHeadingDeg - targetDegs) < 180:
tranx = 4
motorDuration = 10print (intHeadingDeg - targetDegs)
skriva ut "Vänster 1" elif intHeadingDeg > = targetDegs:
IF1 < (targetDegs - intHeadingDeg):
#abs (intHeadingDeg - targetDegs) < = 180:
tranx = 2
motorDuration = 10print (intHeadingDeg - targetDegs)
skriva ut "Rätt 2" elif1 > (targetDegs - intHeadingDeg):
#abs (intHeadingDeg - targetDegs) > 180:
tranx = 4
motorDuration = 10print (intHeadingDeg - targetDegs)
skriva ut "Vänster 2" #/ / / slutet flytta Bot ///#///CV Dawing / / / #Target cirkel
CV2.Circle (ram, (tX, tY), 10, (0, 0, 255), tjocklek =-1)
#ser.write (botXY) #Background för text.
CV2.Rectangle (ram, (18,2), (170,160), (255,255,255), -1)
#Target vinkel.
CV2.line (ram, (tX, tY), (cxAvg,cyAvg),(0,255,0), 1)
#Bot's X och Y är skriven till bild
CV2.putText(Frame,Str(CX) + "cx," + str(cy) + "cy", (20,20), cv2. FONT_HERSHEY_COMPLEX_SMALL,.7,(0,0,0))
#Bot's X- och Y medelvärden skrivs till bild
CV2.putText(Frame,Str(cxAvg) + "cxA," + str(cyAvg) + "cyA", (20,40), cv2. FONT_HERSHEY_COMPLEX_SMALL,.7,(0,0,0))
#"Ok" är skriven till skärmen om X & Y är nära till X & Y Avg för flera iterationer.
CV2.putText (ram, stringXOk, (20,60), cv2. FONT_HERSHEY_COMPLEX_SMALL,.7,(0,0,0))
CV2.putText (ram, stringYOk, (20,80), cv2. FONT_HERSHEY_COMPLEX_SMALL,.7,(0,0,0))
#Print kompassen på ramen.
CV2.putText (ram, "Bot:" + headingDeg + "Deg", (20,100), cv2. FONT_HERSHEY_COMPLEX_SMALL,.7,(0,0,0))
CV2.putText (ram, "mål:" + strTargetDegs + "Deg", (20,120), cv2. FONT_HERSHEY_COMPLEX_SMALL,.7,(0,0,0))
#Dots äts.
CV2.putText (ram, "prickar åt:" + str (prickar), (20,140), cv2. FONT_HERSHEY_COMPLEX_SMALL,.7,(0,0,0))
#After ram har ändrats för helvete, Visa den.
CV2.imshow('frame',Frame) #Color bilden
CV2.imshow('thresh',thresh2) #Black-n-vit tröskel bild #/ / / slutet CV Rita ///if cv2.waitKey (33) == 27:
# Städa upp allt innan avresa
CV2.destroyAllWindows()
Cap.release()
#Tell roboten att stoppa innan du avslutar.
ser.write("5")
ser.Close() # stänger den seriella connection.breakdefrxtx():
# Under 32 är allt i ASCII rotvälska
räknare = 32 #So data kan skickas till OpenCV thread.global rx
globala intRx
globala tranx
globala motorDuration
globala motorBusy
While(true):
räknaren + = 1# läsa nyaste utdata från Arduino
RX = ser.readline()
#This är för gängning ut motor timern. Vilket möjliggör kontroll #over motorn brast duration.if motorBusy == "Nej":
ser.write(tranx)
ser.flushOutput() #Clear bufferten?
motorBusy = "Ja" #Delay en tiondel av en sekund
Sleep(.1)
#This är tänkt för att ta bara de tre första siffrorna.
RX = rx [: 3]
#This tar bort eventuella EOL-tecken
RX = rx.strip()
#If numret är mindre än 3 siffror, då det kommer att ingå #we bli av med det så vi kan ha en ren str till int konvertering.
RX = rx.replace (".", "")
#We gillar inte 0. Så, detta tar bort den. försök:
intRx =int(rx)
exceptValueError:
intRx = 0 #Reset counter om över 255. om counter == 255:
räknare = 32defmotorTimer():
globala motorDuration
globala motorBusy
While(1):
om motorBusy == "Ja":
Sleep(.2) #Sets motorn brast längd.
ser.write("5")
Sleep(.3) #Sets tid emellan motor spricker.
motorBusy = "Nej" #Threads OpenCV grejer.
OpenCV = threading. Thread(Target=opencv)
OpenCV.start()
#Threads seriell funktioner.
rxtx = threading. Thread(Target=rxtx)
rxtx.start()
#Threads de motoriska funktionerna.
motorTimer = threading. Thread(Target=motorTimer)
motorTimer.start()