PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schnelle(!) Objekterkennung mit Raspi+USB-Cam



phantom111
01.03.2013, 10:26
Hallo,

OpenCV kommt auf dem Raspberry PI nur auf wenige FPS.
Ich bin mir nicht ganz sicher, ob OpenCV da nicht zu komplexe Sachen macht. Was meint ihr, gibt es da noch Optimierungsmöglichkeiten?
Es geht z.B. um eine Ballerkennung (nach Farbe).

Danke,Grüße!

Cyclon
01.03.2013, 17:34
Klar gibt's da Optimierungsmöglichkeiten...sogar jede Menge...
Die erste wäre z.B. uns zu zeigen, wie dein Programm und dein Code aussieht.... Denn weder ich noch die 55 anderen, die sich den Thread vor mir angesehen haben, werden Lust haben zu raten

phantom111
01.03.2013, 18:00
Wenn ich in OpenCV ein nur(!) ein cv.CreateCameraCapture(0) in einer Schleife mache, komme ich auf 4 fps (mit 320x240). Deswegen brauche ich doch gar keinen weiteren Code geben. Mit OpenCV haben auch andere schon solche Erfahrungen gemacht. Diesen Code habe ich auch getestet: http://dl.dropbox.com/u/2500608/LaserDuck.py

ichbinsisyphos
01.03.2013, 18:34
Ich kann mir da nicht sicher sein, aber mit CreateCameraCapture() holt er wohl nur das rohe Bild von der Kamera, oder? Wenn dir das alleine schon zu langsam ist, dann wird man da innerhalb von opencv wohl nicht viel optimieren können, weil er sich in dem Schritt noch gar nicht mit irgendwelcher Objekterkennung beschäftigt.

phantom111
01.03.2013, 18:39
genau das habe ich mir auch gedacht.

ichbinsisyphos
01.03.2013, 19:49
Hast mal online gesucht, ob jemand anderes Erfahrungen mit der selben Kamera in opencv hat?

Was ich jetzt so gefunden habe, sind diese 3-4fps auf dem Rasberry Pi mit opencv nicht ungewöhnlich. Kriegst du die frames nicht auch mit einem anderen capture-Programm rein?

phantom111
01.03.2013, 19:52
Ja, genau. Mit OpenCV ist das wohl normal. Deswegen will ich ja auch weg von dieser Lib. Habe schon mehrere Beispiele gefunden aber da liegt im Grunde immer OpenCV hinter. Was sind echte Alternativen? Was bringt etwas?

ichbinsisyphos
01.03.2013, 20:31
Was das capturing alleine angeht, da gibts jede Menge Alternativen, das geht schon mit mplayer/VLC/ffmpeg/... aber ich hab damit keine Erfahrung, da gibts sicher weit effizientere Methoden.
Der Rasberry Pi hat doch ein einigermaßen ausgewachsenes Linux, oder?

PyGame hat da anscheinend Funktionen, wenn du Python verwenden willst
http://www.pygame.org/docs/tut/camera/CameraIntro.html

Andere Möglichkeit wäre Video For Linux V4L2, aber da wühlt man schon im Kernel rum.

Aber wer weiß, ob es das externe capturing überhaupt bringt, für die Objekterkennung wirst kaum Alternativen finden.

EZ81
02.03.2013, 02:24
Wenn ich in OpenCV ein nur(!) ein cv.CreateCameraCapture(0) in einer Schleife mache, komme ich auf 4 fps (mit 320x240). Deswegen brauche ich doch gar keinen weiteren Code geben.

Das ist so auch etwas seltsam, da cvCreateCameraCapture() die Kamera initialisiert.

Die Doku verstehe ich so:


# 1 mal am Anfang:
capture = cv.CreateCameraCapture(0)
while True:
frame = cv.QueryFrame(capture)

m.a.r.v.i.n
02.03.2013, 12:14
Kennst du dieses Video:

https://www.youtube.com/watch?v=A7Bnm92om2E&feature=player_embedded
9fps sollten schon möglich sein. Allerdings wird hier ein RasPi mit 512MB verwendet.

ichbinsisyphos
02.03.2013, 13:14
Das lustige ist, dass so viele Leute zum Holen des Bildes von der Kamera ohne irgendwelche anderen Algorithmen schon nur 3-4fps haben. Beim OP wird das jetzt schneller gehen, wenn er wirklich bei jedem Durchlauf die Kamera initialisiert hat, aber das gilt für viele der anderen Leidensgenossen nicht. OpenCV scheint da sehr verschwenderisch mit den Resourcen umzugehen.

phantom111
02.03.2013, 17:42
OK, danke. Das Initialisieren hatte ich leider nicht in der Schleife. Habe mich vertippt. Schade eigentlich. Die Lösung wäre einfach gewesen.

Hier mein Code. Ich mache das in der Schleife. Danach gehe ich durch die Elemente in contour. Es werden sehr viele gefunden. Das macht alles sehr langsam. Wo ist der Fehler!?



color_image = cv.QueryFrame(self.capture)
cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 3, 0)
cv.Threshold(grey_image, grey_image, 70, 255, cv.CV_THRESH_BINARY)
down = cv.Scalar(10,100,100,0) # cv.Scalar(30,100,100) #
up = cv.Scalar(40, 255,255,0) #(35,255,255)
imghsv=cv.CreateImage(cv.GetSize(color_image),8,3)
cv.CvtColor(color_image,imghsv,cv.CV_BGR2HSV) # Convert image from RGB to HSV

imgyellow=cv.CreateImage(cv.GetSize(color_image),8 ,1)
imgthreshold=cv.CreateImage(cv.GetSize(color_image ),8,1)
cv.InRangeS(imghsv,down,up,imgyellow) # Select a range of yellow color
storage = cv.CreateMemStorage(0)
contour = cv.FindContours(imgthreshold, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE)

schorsch_76
02.03.2013, 18:16
Das lustige ist, dass so viele Leute zum Holen des Bildes von der Kamera ohne irgendwelche anderen Algorithmen schon nur 3-4fps haben. Beim OP wird das jetzt schneller gehen, wenn er wirklich bei jedem Durchlauf die Kamera initialisiert hat, aber das gilt für viele der anderen Leidensgenossen nicht. OpenCV scheint da sehr verschwenderisch mit den Resourcen umzugehen.

OpenCV ist hier eher resourcenschonend. Meist ist das Problem nicht die Software sondern die Verbindung. Bsp. USB 1 statt USB 2. Auch in der industriellen Bildverarbeitung ist das reine Bild einziehen meist sehr untergeordnet. Die Anzeigealgorithmen haben bsp. nichts mit dem Bildeinzug gemein. Wenn es um den Bildeinzug geht, eben nur einziehen und nicht anzeigen. Hier ist dann auch nochmal ein Flaschenhals. Bsp. nicht funktionierende Hardwarebeschleunigung.

Gruß
Georg

phantom111
02.03.2013, 18:24
Ich habe die hier http://download.p4c.philips.com/files/s/spc520nc_00/spc520nc_00_pss_deu.pdf
Der Code dort oben kommt auf 10 fps. Problem ist, das Durchlaufen durch die "contour" (Liste).



while contour:

bound_rect = cv.BoundingRect(list(contour))
contour = contour.h_next()

pt1 = (bound_rect[0], bound_rect[1])
pt2 = (bound_rect[0] + bound_rect[2], bound_rect[1] + bound_rect[3])
points.append(pt1)
points.append(pt2)
centroidx=cv.Round((pt1[0]+pt2[0])/2)
centroidy=cv.Round((pt1[1]+pt2[1])/2)
centroid = (centroidx, centroidy)
if len(points):
radius = abs(pt1[0]-pt2[0])/2
if True: #radius > 2 and radius != 159:
self.centroid = centroid
self.radius = radius
if self.gui is True:
cv.Circle(color_image, centroid , radius , cv.CV_RGB(255,0,0), 1)
cv.Rectangle(color_image, pt1, pt2, cv.CV_RGB(255,0,0), 1)
cv.PutText(color_image, str(centroid)+" r="+str(radius), centroid, cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0, 2, 1), cv.CV_RGB(255,0,0))
# print str(centroid)+" r="+str(radius)
else:
self.centroid = None
self.radius = None

EZ81
02.03.2013, 18:56
Auf meinem Core2Duo mit 1.8GHz schafft der Code im Anhang (deine Schnipsel halbwegs lauffähig gemacht) mit Anzeigefenster auch nur ~22 Frames/s mit einer Playstation Eye (640x480, 30fps), ohne die contour-Liste immerhin 24fps. Ohne Gui schafft er in beiden Fällen fast 30fps. Die 4 fps auf der RasPi scheinen also leider realistisch.
Ein winziges Stück mehr Geschwindigkeit brachte es, das cv.CreateMemStorage(0) vor die Endlos-Schleife zu setzen.

phantom111
02.03.2013, 19:14
ich könnte mir vorstellen, dass in contour einfach zu viele Objekte drin sind. Vielleicht kann man irgendwie in der Richtung optimieren.

phantom111
03.03.2013, 15:41
9 fps mit folgendem Code.


import cv2
import cv as cv
import numpy as np
import time

show = False

c = cv2.VideoCapture(0)
c.set(3, 320)
c.set(4, 240)
width,height = c.get(3),c.get(4)
print "width, height = ", width, ",", height

start_time = time.time()
i = 0
while(1):
_,f = c.read()

#f = cv2.flip(f,1)
#blur = cv2.medianBlur(f,5)
hsv = cv2.cvtColor(f,cv2.COLOR_BGR2HSV)
yellow = cv2.inRange(hsv,np.array((20,100,100)),np.array((3 0,255,255)))
erode = cv2.erode(yellow,None,iterations = 3)
dilate = cv2.dilate(erode,None,iterations = 10)
contours,hierarchy = cv2.findContours(dilate,cv2.RETR_LIST,cv2.CHAIN_AP PROX_SIMPLE)

for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
cx,cy = x+w/2, y+h/2

print "yellow :", x,y,w,h
if show:
cv2.rectangle(f,(x,y),(x+w,y+h),[0,255,255],2)
cv2.imshow('img',f)
if cv2.waitKey(25) == 27:
break

cv2.destroyAllWindows()
c.release()

Mandar Gole
05.02.2014, 13:14
Hey hi Leute!!!

Ich bin neu zu diesem Forum. Ich bin ein student des Studiengang Mechatronik und bin gerade an der Arbeit mit Bilderkennung der Balle.

Ich arbeite mit Matlab-Simulink.

Ich kann Kreise erkennen, aber die Balle ist immer noch schwer.

Sag mal bitte ein paar Tips und Tricks!!!

Danke im Vorraus,

Gruß
Mandar

phantom111
05.02.2014, 14:50
Hallo,

ich verstehe die Frage nicht.
Was ist der Unterschied zwischen einem Kreis im Bild und einem Ball?
Vielleicht, dass der Ball aufgrund der 3D-Form "unterschiedliche Farben hat"? Vielleicht brauchst Du dafür Schwellwerte (siehe cv2.inRange() in meinem Code)

Viele Grüße

Mandar Gole
20.02.2014, 13:18
Ja, du hast es recht. Es gibt kein Unterschied ywischen ein Ball und ein Kreis. Ich benutze zur Zeit Matlab R2012a aber will Opencv2.4.8 benutzen. Kann jemand mir die 'Installations Procedure' erzählen. Ein English link würde Super Geil!!! Also ich habe kein Visual Studio, bitte achten!

Danke im Vorraus,

VG
Mandar