Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Automatisch volgen van zichtobjecten

Een pan/tilt-servo-apparaat dat een camera om kleurobjecten automatisch te volgen met behulp van vision.

Verhaal

Inleiding

In mijn laatste tutorial hebben we onderzocht hoe je een pan/tilt-servo-apparaat bedient om een ​​PiCam te positioneren. Nu gaan we ons apparaat gebruiken om de camera te helpen kleurobjecten automatisch te volgen

Dit is mijn eerste ervaring met OpenCV en ik moet bekennen dat ik verliefd ben op deze fantastische "Open Source Computer Vision Library".

OpenCV is gratis voor zowel academisch als commercieel gebruik. Het heeft C++, C, Python en Java interfaces en ondersteunt Windows, Linux, Mac OS, iOS en Android. In mijn reeks OpenCV-tutorials zullen we ons concentreren op Raspberry Pi (dus Raspbian als OS) en Python. OpenCV is ontworpen voor rekenefficiëntie en met een sterke focus op realtime toepassingen. Het is dus perfect voor fysieke computerprojecten!

Stap 1:Stuklijst – Stuklijst

Belangrijkste onderdelen:

  • Raspberry Pi V3 - US$ 32,00
  • 5 Megapixel 1080p Sensor OV5647 Mini Camera Video Module - US$ 13,00
  • TowerPro SG90 9G 180 graden microservo (2 X)- US$ 4,00
  • Mini pan/tilt cameraplatform Anti-vibratie camerabevestiging met 2 servo's (*) – US$ 8,00
  • LED rood
  • Weerstand 220 ohm
  • Weerstand 1K ohm (2X) – Optioneel
  • Diversen:metalen onderdelen, banden, enz (voor het geval je je Pan/Tilt-mechanisme gaat bouwen)

(*) je kunt een compleet Pan/Tilt-platform kopen met de servo's of je eigen platform bouwen.

Stap 2:OpenCV 3-pakket installeren

Ik gebruik een Raspberry Pi V3 die is bijgewerkt naar de laatste versie van Raspbian (Stretch), dus de beste manier om OpenCV te installeren, is door de uitstekende tutorial te volgen die is ontwikkeld door Adrian Rosebrock: Raspbian Stretch:Install OpenCV 3 + Python op je Raspberry Pi.

Ik heb verschillende handleidingen geprobeerd om OpenCV op mijn Pi te installeren. Adrian's tutorial is de beste. Ik raad je aan hetzelfde te doen en zijn richtlijn stap voor stap te volgen.

Als je de tutorial van Adrian hebt voltooid, zou je een virtuele OpenCV-omgeving moeten hebben om onze experimenten op je Pi uit te voeren.

Laten we naar onze virtuele omgeving gaan en controleren of OpenCV 3 correct is geïnstalleerd.

Adrian raadt aan om elke keer dat je een nieuwe terminal opent het commando "source" uit te voeren om er zeker van te zijn dat je systeemvariabelen correct zijn ingesteld.

bron ~/.profile

Laten we vervolgens onze virtuele omgeving invoeren:

werk op cv

Als u de tekst (cv) voor uw prompt ziet, bevindt u zich in de cv virtual omgeving:

(cv) pi@raspberry:~$

Adrian vestigt de aandacht op de cv Python virtuele omgeving is volledig onafhankelijk en afgezonderd van de standaard Python-versie die is opgenomen in de download van Raspbian Stretch. Dus alle Python pakketten in de globale site-packages directory zullen niet beschikbaar zijn voor de cv virtuele omgeving. Evenzo zullen alle Python-pakketten die zijn geïnstalleerd in site-pakketten van cv niet beschikbaar zijn voor de algemene installatie van Python.

Voer nu uw Python-interpreter in:

python

en bevestig dat je versie 3.5 (of hoger) gebruikt

In de interpreter (de ">>>" zal verschijnen), importeer de OpenCV-bibliotheek:

cv2 importeren

Als er geen foutmeldingen verschijnen, is de OpenCV correct geïnstalleerd OP UW VIRTUELE PYTHON-OMGEVING.

U kunt ook de geïnstalleerde OpenCV-versie controleren:

cv2.__version__

De 3.3.0 zou moeten verschijnen (of een betere versie die in de toekomst kan worden uitgebracht). De bovenstaande Terminal PrintScreen toont de vorige stappen.

Stap 3:Uw camera testen

Zodra OpenCV in uw RPi is geïnstalleerd, gaan we testen of uw camera goed werkt.

Ik neem aan dat je al een PiCam op je Raspberry Pi hebt geïnstalleerd.

Voer de onderstaande Python-code in op uw IDE:

import numpy as npimport cv2cap =cv2.VideoCapture(0)while(True):ret, frame =cap.read() frame =cv2.flip(frame, -1) # Camera verticaal kantelen grijs =cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow('frame', frame) cv2.imshow('gray', grijs) if cv2.waitKey(1) &0xFF ==ord('q'):breakcap.release()cv2.destroyAllWindows()

De bovenstaande code legt de videostream vast die door uw PiCam wordt gegenereerd en geeft deze zowel in BGR-kleur als in grijsmodus weer.

Merk op dat ik mijn camera verticaal heb gedraaid vanwege de manier waarop deze is gemonteerd. Als dit niet jouw geval is, becommentarieer of verwijder de "flip"-opdrachtregel.

Je kunt de code ook downloaden van mijn GitHub: simpleCamTest.py

Voer het commando in om uit te voeren:

python simpleCamTest.py

Om het programma te beëindigen, moet je op de toets [q] tor [Ctrl] + [C] op je toetsenbord drukken

De afbeelding toont het resultaat.

Als je meer wilt weten over OpenCV, kun je de tutorial volgen: loading -video-python-opencv-tutorial

Stap 4:Kleurdetectie in Python met OpenCV

Eén ding dat we zullen proberen te bereiken, is het detecteren en volgen van een bepaald kleurobject. Daarvoor moeten we wat meer begrijpen over hoe OpenCV kleuren interpreteert.

Henri Dang heeft een geweldige tutorial geschreven over kleurdetectie in Python met OpenCV.

Normaal gesproken werkt onze camera met de RGB-kleurmodus, wat begrepen kan worden door het te zien als alle mogelijke kleuren die kunnen worden gemaakt van drie gekleurde lichten voor rood, groen en blauw. In plaats daarvan werken we hier met BGR (Blauw, Groen, Rood).

Zoals hierboven beschreven, wordt een pixel met BGR weergegeven door drie parameters:blauw, groen en rood. Elke parameter heeft meestal een waarde van 0 – 255 (of O tot FF in hexadecimaal). Een puur blauwe pixel op uw computerscherm heeft bijvoorbeeld een B-waarde van 255, een G-waarde van 0 en een R-waarde van 0.

OpenCV werkt met het HSV-kleurmodel (Hue, Saturation, Value), dat een alternatieve weergave is van het RGB-kleurmodel, ontworpen in de jaren 70 door computergraphics-onderzoekers om beter af te stemmen op de manier waarop mensen vision neemt attributen voor het maken van kleuren waar:

Geweldig. Dus als u een bepaalde kleur wilt volgen met OpenCV, moet u deze definiëren met behulp van het HSV-model.

Voorbeeld

Laten we zeggen dat ik een geel object moet volgen zoals de plastic doos op de afbeelding hierboven. Het gemaksgedeelte is om de BGR-elementen te vinden. Je kunt elk ontwerpprogramma gebruiken om het te vinden (ik gebruikte PowerPoint).

In mijn geval vond ik:

  • Blauw:71
  • Groen:234
  • Rood:213

Vervolgens moeten we het BGR-model (71, 234, 213) converteren naar een HSV-model, dat wordt gedefinieerd met boven- en ondergrenzen. Laten we daarvoor de onderstaande code uitvoeren:

import sysimport numpy as npimport cv2blue =sys.argv[1]green =sys.argv[2]red =sys.argv[3] color =np.uint8([[[blue, green] , rood]]])hsv_color =cv2.cvtColor(color, cv2.COLOR_BGR2HSV)hue =hsv_color[0][0][0]print("Ondergrens is :"),print("[" + str(hue- 10) + ", 100, 100]\n")print("Bovengrens is :"),print("[" + str(hue + 10) + ", 255, 255]")

Je kunt de code ook downloaden van mijn GitHub: bgr_hsv_converter.py

Voer het onderstaande commando in met als parameters de eerder gevonden BGR-waarden:

python bgr_hsv_converter.py 71 234 213

Het programma drukt de boven- en ondergrenzen van onze objectkleur af.

In dit geval:

ondergrens:[24, 100, 100]

en

bovengrens:[44, 255, 255]

Het Terminal PrintScreen toont het resultaat.

Laten we tot slot eens kijken hoe OpenCV ons object kan "maskeren" als we de kleur eenmaal hebben bepaald:

import cv2import numpy as np# Lees de afbeelding - De 1 betekent dat we de afbeelding in BGRimg =cv2.imread('yellow_object.JPG', 1) # resize imag naar 20% in elke axisimg =cv2.resize(img, (0,0), fx=0.2, fy=0.2)# converteer BGR-afbeelding naar een HSV-afbeeldinghsv =cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # NumPy om arrays te maken om onder en boven vast te houden bereik # Het "dtype =np.uint8" betekent dat het gegevenstype een 8 bit integerlower_range =np.array([24, 100, 100], dtype=np.uint8) upper_range =np.array([44, 255, 255) is ], dtype=np.uint8)# maak een masker voor imagemask =cv2.inRange(hsv, lower_range, upper_range)# toon zowel het masker als de afbeelding naast elkaarcv2.imshow('mask',mask)cv2.imshow ('image', img)# wacht tot de gebruiker op [ ESC ] drukt terwijl(1):k =cv2.waitKey(0) if(k ==27):breakcv2.destroyAllWindows()

Je kunt de code ook downloaden van mijn GitHub: colorDetection.py

Om uit te voeren, voert u het onderstaande commando in met in uw directory een foto met uw doelobject (in mijn geval:yellow_object.JPG):

python colorDetection.py

De bovenstaande afbeelding toont de originele afbeelding ("afbeelding") en hoe het object eruit zal zien ("masker") nadat het masker is toegepast.

Stap 5:Objectbeweging volgen

Nu we weten hoe we ons object moeten 'selecteren' met een masker, gaan we de beweging ervan in realtime volgen met de camera. Daarvoor heb ik mijn code gebaseerd op de zelfstudie Ball Tracking with OpenCV van Adrian Rosebrock.

Ik raad je ten zeerste aan om Adrians tutorial in detail te lezen.

Controleer eerst of u de imutils-bibliotheek heeft geïnstalleerd. het is Adrian's verzameling OpenCV-gemaksfuncties om een ​​paar basistaken (zoals het formaat wijzigen of het scherm omdraaien) veel gemakkelijker te maken. Zo niet, voer dan het onderstaande commando in om de bibliotheek op uw Virtual Python-omgeving te installeren:

pip install imutils

Download vervolgens de code ball_tracking.py van mijn GitHub en voer deze uit met de opdracht:

python ball_traking.py

In principe is het dezelfde code als die van Adrian, behalve de "video verticale flip", die ik kreeg met de regel:

frame =imutils.rotate(frame, angle=180)

Houd er ook rekening mee dat de gebruikte maskergrenzen degene waren die we in de vorige stap hebben gekregen.

Stap 6:De GPIO's testen

Nu we met de basis van OpenCV hebben gespeeld, gaan we een LED op onze RPi installeren en beginnen met de interactie met onze GPIO's.

Volg het bovenstaande elektrische schema:De kathode van de LED wordt verbonden met GPIO 21 en zijn anode met GND via een weerstand van 220 ohm.

Laten we onze LED testen in onze virtuele Python-omgeving.

Onthoud dat het mogelijk is dat RPi.GPIO niet is geïnstalleerd in uw virtuele Python-omgeving! Om dit probleem op te lossen, moet je, zodra je daar bent (vergeet niet om te bevestigen dat de (cv) in je terminal staat), pip gebruiken om het in je virtuele omgeving te installeren:

pip install RPi.GPIO

Laten we het python-script gebruiken om een ​​eenvoudige test uit te voeren:

import sysimport timeimport RPi.GPIO als GPIO# initialiseer GPIO en variabelenredLed =int(sys.argv[1])freq =int(sys.argv[2])GPIO.setmode(GPIO.BCM )GPIO.setup(redLed, GPIO.OUT)GPIO.setwarnings(False)print("\n [INFO] Knipperende LED (5 keer) verbonden met GPIO {0} om de {1} seconde(n)".format( redLed, freq)) voor i binnen bereik (5):GPIO.output (redLed, GPIO.LOW) time.sleep (freq) GPIO.output (redLed, GPIO.HIGH) time.sleep (freq) # doe een beetje cleanupprint("\n [INFO] Programma afsluiten en dingen opschonen \n")GPIO.cleanup()

Deze code ontvangt als argument een GPIO-nummer en de frequentie in seconden dat onze LED moet knipperen. De LED knippert 5 keer en het programma wordt beëindigd. Houd er rekening mee dat we de GPIO's zullen bevrijden voordat we beëindigen.

Dus om het script uit te voeren, moet u als parameters LED GPIO invoeren , en frequentie .

Bijvoorbeeld:

python LED_simple_test.py 21 1

De bovenstaande opdracht knippert elke "1" seconde 5 keer de rode LED die is aangesloten op "GPIO 21".

Het bestand GPIO_LED_test.py kan worden gedownload van mijn GitHub

Het bovenstaande Terminal-afdrukscherm toont het resultaat (en natuurlijk moet u bevestigen dat de LED knippert.

Laten we nu eens werken met OpenCV en wat basis GPIO-dingen.

Stap 7:Herkennen van kleuren en GPIO-interactie

Laten we beginnen met het integreren van onze OpenCV-codes met GPIO-interactie. We beginnen met de laatste OpenCV-code en we zullen de GPIO-RPI-bibliotheek erop integreren, dus we zullen de rode LED inschakelen wanneer ons gekleurde object door de camera wordt gevonden. De code die in deze stap werd gebruikt, was gebaseerd op Adrian's geweldige tutorial OpenCV, RPi.GPIO en GPIO Zero op de Raspberry Pi:

Het eerste dat u moet doen, is onze LED "creëren" en deze verbinden met de specifieke GPIO:

importeer RPi.GPIO als GPIOredLed =21GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)GPIO.setup(redLed, GPIO.OUT)

Ten tweede moeten we onze LED initialiseren (uitgeschakeld):

GPIO.output(redLed, GPIO.LOW)ledOn =False

Nu, binnen de lus, waar de "cirkel" wordt gemaakt wanneer het object wordt gevonden, zullen we de LED inschakelen:

GPIO.output(redLed, GPIO.HIGH)ledOn =True

Laten we de volledige code downloaden van mijn GitHub: object_detection_LED.py

Voer de code uit met het commando:

python object_detection_LED.py

Probeer het met verschillende objecten (kleur en formaat). U zult zien dat zodra de kleur binnen de maskergrenzen overeenkomt, de LED wordt ingeschakeld.

De onderstaande video toont enkele ervaringen. Houd er rekening mee dat alleen gele objecten die binnen het kleurbereik blijven, worden gedetecteerd, waardoor de LED gaat branden. Objecten met verschillende kleuren worden genegeerd.

We gebruiken hier alleen de LED zoals uitgelegd in de laatste stap. Ik had mijn Pan Tilt al in elkaar gezet toen ik de video maakte, dus negeer het. In de volgende stap zullen we het PAN/TILT-mechanisme gebruiken.

Stap 8:Het Pan Tilt Mechanisme

Nu we met de basis van OpenCV en GPIO hebben gespeeld, gaan we ons Pan/tilt-mechanisme installeren.

Ga voor meer informatie naar mijn tutorial: Pan-Tilt-Multi-Servo-Control

De servo's moeten worden aangesloten op een externe 5V-voeding, waarbij hun datapin (in mijn geval hun gele bedrading) wordt aangesloten op Raspberry Pi GPIO zoals hieronder:

  • GPIO 17 ==> Kantelservo
  • GPIO 27 ==> Pan-servo

Vergeet niet de GND's met elkaar te verbinden ==> Raspberry Pi – Servo’s – Externe voeding)

U kunt als optie een weerstand van 1K ohm in serie hebben tussen Raspberry Pi GPIO en Server-gegevensinvoerpin. Dit zou je RPi beschermen in geval van een servoprobleem.

Laten we ook van de gelegenheid gebruik maken en onze servo's testen in onze virtuele Python-omgeving.

Laten we het Python-script gebruiken om enkele tests uit te voeren met onze stuurprogramma's:

from time import sleepimport RPi.GPIO as GPIOGPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)def setServoAngle(servo, angle):pwm =GPIO.PWM(servo, 50) pwm .start(8) dutyCycle =hoek / 18. + 3. pwm.ChangeDutyCycle(dutyCycle) sleep(0.3) pwm.stop()if __name__ =='__main__':import sys servo =int(sys.argv[1]) GPIO.setup(servo, GPIO.OUT) setServoAngle(servo, int(sys.argv[2])) GPIO.cleanup()

De kern van bovenstaande code is de functie setServoAngle(servo, angle). Deze functie ontvangt als argument een servo GPIO-nummer en een hoekwaarde naar waar de servo moet worden geplaatst. Zodra de invoer van deze functie "hoek" is, moeten we deze converteren naar een equivalente werkcyclus.

Om het script uit te voeren, moet u als parameters servo GPIO invoeren , en hoek .

Bijvoorbeeld:

python angleServoCtrl.py 17 45

Het bovenstaande commando plaatst de servo aangesloten op GPIO 17 ("tilt") met 45 graden in "elevatie".

Het bestand angleServoCtrl.py kan worden gedownload van mijn GitHub

Stap 9:De realtime positie van het object vinden

Het idee hier is om het object in het midden van het scherm te plaatsen met behulp van het Pan/Tilt-mechanisme. Het slechte nieuws is dat we om te beginnen in realtime moeten weten waar het object zich bevindt. Maar het goede nieuws is dat het heel gemakkelijk is als we de coördinaten van het objectcentrum al hebben.

Laten we eerst de eerder gebruikte code "object_detect_LED" nemen en deze wijzigen om de x,y-coördinaten van het opgerichte object af te drukken.

Download van mijn GitHub de code: objectDetectCoord.py

De "kern" van de code is het gedeelte waar we het object vinden en er een cirkel op tekenen met een rode stip in het midden.

# ga alleen verder als de straal een minimumgrootte heeft als straal> 10:# teken de cirkel en het zwaartepunt op het frame, # werk vervolgens de lijst met gevolgde punten bij cv2.circle(frame, (int( x), int(y)), int(straal), (0, 255, 255), 2) cv2.circle(frame, center, 5, (0, 0, 255), -1) # print middelpunt van cirkel coördinaten mapObjectPosition(int(x), int(y)) # als de led nog niet aan is, zet hem dan aan als dat niet het geval is ledOn:GPIO.output(redLed, GPIO.HIGH) ledOn =True

Laten we de middencoördinaten 'exporteren' naar mapObjectPosition(int(x), int(y)) functie om de coördinaten ervan af te drukken. Hieronder de functie:

def mapObjectPosition (x, y):print ("[INFO] Objectcentrum coördineert op X0 ={0} en Y0 ={1}".format(x, y))

Als we het programma uitvoeren, zullen we op onze terminal de (x, y) positiecoördinaten zien, zoals hierboven weergegeven. Verplaats het object en observeer de coördinaten. We zullen ons realiseren dat x van 0 naar 500 gaat (van links naar rechts) en y van o naar 350 (van boven naar beneden). Zie de bovenstaande foto's.

Geweldig! Nu moeten we die coördinaten gebruiken als uitgangspunt voor ons Pan/Tilt-volgsysteem

Stap 10:Objectpositievolgsysteem

We willen dat ons object altijd gecentreerd op het scherm blijft. Laten we dus definiëren dat we ons object als "gecentreerd" beschouwen als:

  • 220
  • 160

Buiten die grenzen moeten we ons Pan/Tilt-mechanisme verplaatsen om afwijkingen te compenseren. Op basis daarvan kunnen we de functie mapServoPosition(x, y) bouwen zoals hieronder. Merk op dat de "x" en "y" die als parameters in deze functie worden gebruikt, dezelfde zijn die we eerder hebben gebruikt voor het afdrukken van de centrale positie:

# positioneer servo's om object in het midden van de framedef te presenteren mapServoPosition (x, y):global panAngle global tiltAngle if (x <220):panAngle +=10 if panAngle> 140:panAngle =140 positionServo (panServo, panAngle) indien (x> 280):panAngle -=10 indien panAngle <40:panAngle =40 positionServo (panServo, panAngle) indien (y <160):tiltAngle +=10 indien tiltAngle> 140:tiltAngle =140 positionServo (tiltServo, tiltAngle) indien (y> 210):tiltAngle -=10 indien tiltAngle <40:tiltAngle =40 positionServo (tiltServo, tiltAngle)

Op basis van de (x, y)-coördinaten worden servopositie-opdrachten gegenereerd met behulp van de functie positionServo(servo, angle). Stel bijvoorbeeld dat de y-positie "50" is, wat betekent dat ons object bijna bovenaan het scherm staat, dat kan worden vertaald dat "camerazicht" "laag" is (laten we zeggen een kantelhoek van 120 graden) Dus we moeten de kantelhoek "verkleinen" (laten we zeggen tot 100 graden), dus het cameravizier zal "omhoog" zijn en het object zal "naar beneden" gaan op het scherm (y zal toenemen tot laten we zeggen 190).

Het bovenstaande diagram toont het voorbeeld in termen van geometrie.

Bedenk hoe de Pan-camera zal werken. merk op dat het scherm niet spiegelt, wat betekent dat als je het object naar "links" beweegt, het op het scherm zal bewegen voor "je rechterkant", zodra je in oppositie bent tegen de camera.

De functie positionServo(servo, hoek) kan worden geschreven als:

def positionServo (servo, angle):os.system("python angleServoCtrl.py " + str(servo) + " " + str(angle)) print("[INFO] Servo positioneren op GPIO {0} tot {1} graden\n".format(servo, hoek))

We zullen het eerder getoonde script aanroepen voor servo-positionering.

Houd er rekening mee dat angleServoCtrl.py in dezelfde map moet staan ​​als objectDetectTrac.py

De volledige code kan worden gedownload van mijn GitHub: objectDetectTrack.py

Stap 11:Conclusie

Zoals altijd hoop ik dat dit project anderen kan helpen hun weg te vinden in de opwindende wereld van elektronica!

Ga voor meer informatie en de definitieve code naar mijn GitHub-depot: OpenCV-Object-Face-Tracking

Ga voor meer projecten naar mijn blog: MJRoBot.org

Saludos uit het zuiden van de wereld!

Tot ziens in mijn volgende tutorial!

Bedankt,

Bron:  Automatisch volgen van zichtobjecten


Productieproces

  1. Objectgeoriënteerd programmeren in Python
  2. Raspberry Pi Ball-tracking
  3. Speathe
  4. Realtime gezichtsherkenning:een end-to-end project
  5. Python - Objectgericht
  6. Bepalen van de nauwkeurigheid van dynamische objectvolging
  7. Filter verbetert robotvisie bij schatting van 6D-pose
  8. Wat is een automatische persmachine?
  9. Wat is een automatische powerpers?
  10. Wat is een automatische pijpenbuiger?
  11. Wat is automatische draaitafel?