Hallo, ihr kennt doch sicher das Feature, dass man sich bei manchen Notebooks über die Webcam per Gesichtserkennung anmelden kann. Ich möchte dieses Feature gerne für ein Projekt nutzen. Kennt jemand gute Opensource Lösungen, die auf einem Raspberry Pi laufen? Danke!
OpenCV ist auf dem Pi VERDAMMT langsam, ohne bearbeitung schätz ich das ganze auf ca. 2-3 fps.. Ich denke wenn das Kameramodul endlich verfügbar ist, kann man etwas mit GPU unterstützung machen, aber das ist noch Zukunftsmusik. Auch möglich wäre die (unsichere) Gesichtserkennung von Android zu portieren, das scheint ja auch auf verhältnismäßig langsamen Geräten zu Funktionieren.
xvzf schrieb: > Auch möglich wäre die (unsichere) Gesichtserkennung von Android zu > portieren, das scheint ja auch auf verhältnismäßig langsamen Geräten zu > Funktionieren. Hast du dazu Infos? Sicher muss das Ganze nicht sein. Ist eher eine Spielerei.
Ein Bekannter meinte noch, dass man da evtl. etwas über Google Picassa machen kann.
Jein, wenn du Java kannst, würde ich mir mal den aktuellsten android quellcode ziehen und dann selbst nach face unlock suchen, dabei lernt man auch gleich was dazu :)
Programmierung Gesichtserkennung mit der Web-Camera Author D.Selzer-McKenzie
1 | import processing.video.*; |
2 | |
3 | import monclubelec.javacvPro.*; |
4 | |
5 | import java.awt.*; // pour classes Point , Rectangle.. |
6 | |
7 | import java.util.*; |
8 | |
9 | // Für WebCam:
|
10 | |
11 | Capture cam1; |
12 | |
13 | //GSMovie cam1;
|
14 | |
15 | |
16 | |
17 | OpenCV opencv; // deklariert ein OpenCV Objekt |
18 | |
19 | Rectangle[] faceRect; |
20 | |
21 | |
22 | |
23 | // A list of my Face objects
|
24 | |
25 | ArrayList<Face> faceList; |
26 | |
27 | |
28 | |
29 | // how many have I found over all time
|
30 | |
31 | int faceCount = 0; |
32 | |
33 | |
34 | |
35 | float sum=0; |
36 | |
37 | int scl=1; |
38 | |
39 | int frame=0; |
40 | |
41 | boolean delFaces; |
42 | |
43 | |
44 | |
45 | void setup() { |
46 | |
47 | |
48 | |
49 | // Für WebCam:
|
50 | |
51 | cam1= new Capture(this, 1280, 720); |
52 | |
53 | //cam1 = new GSMovie(this, "maus.mov");
|
54 | |
55 | |
56 | |
57 | // für WebCam auskommentieren:
|
58 | |
59 | //cam1.play();
|
60 | |
61 | cam1.start(); |
62 | |
63 | |
64 | |
65 | // initialisiert OpenCV ---
|
66 | |
67 | opencv = new OpenCV(this); |
68 | |
69 | |
70 | |
71 | //Vorsicht: bei der Arbeit mit einer Datei muss die Größe genau passen!!!
|
72 | |
73 | //opencv.allocate(640, 360);
|
74 | |
75 | opencv.allocate(cam1.width, cam1.height); |
76 | |
77 | |
78 | |
79 | // Für WebCam:
|
80 | |
81 | // opencv.allocate(cam1.getSourceWidth(), cam1.getSourceHeight()); // initialisiert die Buffer von OpenCV
|
82 | |
83 | size (opencv.width(), opencv.height()); |
84 | |
85 | |
86 | |
87 | // Laden Beschreibungsdatei
|
88 | |
89 | opencv.cascade("/usr/share/opencv/haarcascades/", "haarcascade_frontalface_alt_tree.xml"); |
90 | |
91 | |
92 | |
93 | // Liste mit den Gesichtsobjekten
|
94 | |
95 | faceList = new ArrayList<Face>(); |
96 | |
97 | }
|
98 | |
99 | |
100 | |
101 | void draw() { |
102 | |
103 | |
104 | |
105 | // Dateien und die WebCam brauchen etwas Zeit zum Laden
|
106 | |
107 | if (cam1.available()) { |
108 | |
109 | |
110 | |
111 | // Einzelne Frames werden gelesen
|
112 | |
113 | cam1.read(); |
114 | |
115 | opencv.copy(cam1); |
116 | |
117 | |
118 | |
119 | // Schnitt oder Kameraschwenk erkennen
|
120 | |
121 | println(abs(opencv.sum()-sum)/1000000); |
122 | |
123 | if (abs(opencv.sum()-sum)/1000000 >7) delFaces=true; |
124 | |
125 | else delFaces=false; |
126 | |
127 | sum=opencv.sum(); |
128 | |
129 | |
130 | |
131 | // Erkennen
|
132 | |
133 | faceRect = opencv.detect(false); |
134 | |
135 | |
136 | |
137 | image(opencv.getBuffer(), 0, 0); |
138 | |
139 | |
140 | |
141 | //Rechteck zeichnen
|
142 | |
143 | //opencv.drawRectDetect(true);
|
144 | |
145 | |
146 | |
147 | // Code ab hier von Daniel Shiffman
|
148 | |
149 | // SCENARIO 1: faceList is empty
|
150 | |
151 | if (faceList.isEmpty()) { |
152 | |
153 | // Just make a Face object for every face Rectangle
|
154 | |
155 | for (int i = 0; i < faceRect.length; i++) { |
156 | |
157 | faceList.add(new Face(faceRect[i].x, faceRect[i].y, faceRect[i].width, faceRect[i].height)); |
158 | |
159 | }
|
160 | |
161 | // SCENARIO 2: We have fewer Face objects than face Rectangles found from OPENCV
|
162 | |
163 | }
|
164 | |
165 | else if (faceList.size() <= faceRect.length) { |
166 | |
167 | boolean[] used = new boolean[faceRect.length]; |
168 | |
169 | // Match existing Face objects with a Rectangle
|
170 | |
171 | for (Face f : faceList) { |
172 | |
173 | // Find faces[index] that is closest to face f
|
174 | |
175 | // set used[index] to true so that it can't be used twice
|
176 | |
177 | float record = 50000; |
178 | |
179 | int index = -1; |
180 | |
181 | for (int i = 0; i < faceRect.length; i++) { |
182 | |
183 | float d = dist(faceRect[i].x, faceRect[i].y, f.r.x, f.r.y); |
184 | |
185 | if (d < record && !used[i]) { |
186 | |
187 | record = d; |
188 | |
189 | index = i; |
190 | |
191 | }
|
192 | |
193 | }
|
194 | |
195 | // Update Face object location
|
196 | |
197 | used[index] = true; |
198 | |
199 | f.update(faceRect[index]); |
200 | |
201 | }
|
202 | |
203 | // Add any unused faces
|
204 | |
205 | for (int i = 0; i < faceRect.length; i++) { |
206 | |
207 | if (!used[i]) { |
208 | |
209 | faceList.add(new Face(faceRect[i].x, faceRect[i].y, faceRect[i].width, faceRect[i].height)); |
210 | |
211 | }
|
212 | |
213 | }
|
214 | |
215 | // SCENARIO 3: We have more Face objects than face Rectangles found
|
216 | |
217 | }
|
218 | |
219 | else { |
220 | |
221 | // All Face objects start out as available
|
222 | |
223 | for (Face f : faceList) { |
224 | |
225 | f.available = true; |
226 | |
227 | }
|
228 | |
229 | // Match Rectangle with a Face object
|
230 | |
231 | for (int i = 0; i < faceRect.length; i++) { |
232 | |
233 | // Find face object closest to faces[i] Rectangle
|
234 | |
235 | // set available to false
|
236 | |
237 | float record = 50000; |
238 | |
239 | int index = -1; |
240 | |
241 | for (int j = 0; j < faceList.size(); j++) { |
242 | |
243 | Face f = faceList.get(j); |
244 | |
245 | float d = dist(faceRect[i].x, faceRect[i].y, f.r.x, f.r.y); |
246 | |
247 | if (d < record && f.available) { |
248 | |
249 | record = d; |
250 | |
251 | index = j; |
252 | |
253 | }
|
254 | |
255 | }
|
256 | |
257 | // Update Face object location
|
258 | |
259 | Face f = faceList.get(index); |
260 | |
261 | f.available = false; |
262 | |
263 | f.update(faceRect[i]); |
264 | |
265 | }
|
266 | |
267 | // Start to kill any left over Face objects
|
268 | |
269 | for (Face f : faceList) { |
270 | |
271 | if (f.available) { |
272 | |
273 | f.countDown(); |
274 | |
275 | if (f.dead()) { |
276 | |
277 | f.delete = true; |
278 | |
279 | }
|
280 | |
281 | }
|
282 | |
283 | }
|
284 | |
285 | }
|
286 | |
287 | |
288 | |
289 | // Delete any that should be deleted
|
290 | |
291 | for (int i = faceList.size()-1; i >= 0; i--) { |
292 | |
293 | Face f = faceList.get(i); |
294 | |
295 | // Bei einem Schnitt werden alle Gesichter sofort gelöscht
|
296 | |
297 | if (f.delete || delFaces) { |
298 | |
299 | faceList.remove(i); |
300 | |
301 | }
|
302 | |
303 | }
|
304 | |
305 | |
306 | |
307 | // Draw all the faces
|
308 | |
309 | for (int i = 0; i < faceRect.length; i++) { |
310 | |
311 | noFill(); |
312 | |
313 | stroke(255, 0, 0); |
314 | |
315 | rect(faceRect[i].x*scl, faceRect[i].y*scl, faceRect[i].width*scl, faceRect[i].height*scl); |
316 | |
317 | }
|
318 | |
319 | |
320 | |
321 | for (Face f : faceList) { |
322 | |
323 | f.display(); |
324 | |
325 | }
|
326 | |
327 | }
|
328 | |
329 | }
|
330 | |
331 | |
332 | |
333 | void keyReleased() { |
334 | |
335 | if (key == 's' || key == 'S') saveFrame(timestamp()+"_##.png"); |
336 | |
337 | |
338 | |
339 | // for Movie
|
340 | |
341 | //frame+=500;
|
342 | |
343 | //cam1.jump(frame);
|
344 | |
345 | //cam1.play();
|
346 | |
347 | }
|
348 | |
349 | |
350 | |
351 | // timestamp
|
352 | |
353 | String timestamp() { |
354 | |
355 | Calendar now = Calendar.getInstance(); |
356 | |
357 | return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now); |
358 | |
359 | }
|
360 | |
361 | |
362 | |
363 | // Which Face Is Which
|
364 | |
365 | // Daniel Shiffman
|
366 | |
367 | // April 25, 2011
|
368 | |
369 | // http://www.shiffman.net
|
370 | |
371 | |
372 | |
373 | class Face { |
374 | |
375 | |
376 | |
377 | // A Rectangle
|
378 | |
379 | Rectangle r; |
380 | |
381 | |
382 | |
383 | // Am I available to be matched?
|
384 | |
385 | boolean available; |
386 | |
387 | |
388 | |
389 | // Should I be deleted?
|
390 | |
391 | boolean delete; |
392 | |
393 | |
394 | |
395 | // How long should I live if I have disappeared?
|
396 | |
397 | int timer = 63; |
398 | |
399 | |
400 | |
401 | // Assign a number to each face
|
402 | |
403 | int id; |
404 | |
405 | |
406 | |
407 | // Make me
|
408 | |
409 | Face(int x, int y, int w, int h) { |
410 | |
411 | r = new Rectangle(x, y, w, h); |
412 | |
413 | available = true; |
414 | |
415 | delete = false; |
416 | |
417 | id = faceCount; |
418 | |
419 | faceCount++; |
420 | |
421 | }
|
422 | |
423 | |
424 | |
425 | // Show me
|
426 | |
427 | void display() { |
428 | |
429 | fill(0, 0, 255, timer*2); |
430 | |
431 | stroke(0, 0, 255); |
432 | |
433 | rect(r.x*scl, r.y*scl, r.width*scl, r.height*scl); |
434 | |
435 | fill(255, timer*2); |
436 | |
437 | text(""+id, r.x*scl+10, r.y*scl+30); |
438 | |
439 | }
|
440 | |
441 | |
442 | |
443 | // Give me a new location / size
|
444 | |
445 | // Oooh, it would be nice to lerp here!
|
446 | |
447 | void update(Rectangle newR) { |
448 | |
449 | r = (Rectangle) newR.clone(); |
450 | |
451 | }
|
452 | |
453 | |
454 | |
455 | // Count me down, I am gone
|
456 | |
457 | void countDown() { |
458 | |
459 | timer--; |
460 | |
461 | }
|
462 | |
463 | |
464 | |
465 | // I am deed, delete me
|
466 | |
467 | boolean dead() { |
468 | |
469 | if (timer < 0) return true; |
470 | |
471 | return false; |
472 | |
473 | }
|
474 | |
475 | }
|
-- Quelltext in [ c ] [ /c ] einschließen. Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang -rufus
:
Bearbeitet durch User
xvzf schrieb: > OpenCV ist auf dem Pi VERDAMMT langsam Die Himbeer-Alternative besorgen: Odroid C1 Raspberry mit quadcore, 1,5GHz, 1GB RAM usw, aber zum aehnlichen Preis wie die Himmbeere. http://www.heise.de/hardware-hacks/meldung/Odroid-C1-Raspberry-Pi-Konkurrent-in-den-Startloechern-2487225.html http://www.hardkernel.com/main/products/prdt_info.php?g_code=G141578608433 Hier bestellen: http://www.pollin.de/shop/dt/MTI2OTgxOTk-/Bausaetze_Module/Entwicklerboards/ODROID_C1_Einplatinen_Computer_1_5_GHz_QuadCore_4x_USB_1_GB.html PiPi schrieb: > Ich möchte dieses Feature gerne für ein Projekt nutzen. Kennt jemand > gute Opensource Lösungen, die auf einem Raspberry Pi laufen? Wie gesagt: OpenCV (C++) oder PyCV (das selbe nur fuer Python) Auf dem RPi wuerd ich aber C++ vorziehen. Fuer 'Face Tracking' bzw. Gesichtserkennung mit OpenCV gibt es auch viele Beispiele im Netz, das kannst du dann ja so anpassen, wie du es brauchst. http://mymobilerobots.com/myblog/academic/tutorial-opencv-2-4-3-face-tracking-detection-using-vs-2010-c/ http://opencv-code.com/tutorials/eye-detection-and-tracking/ http://www.instructables.com/id/Face-detection-and-tracking-with-Arduino-and-OpenC/
Outbackbrumby schrieb: > Programmierung Gesichtserkennung mit der Web-Camera > > Author D.Selzer-McKenzie Wer soll dieses Kraut eigentlich lesen? Selbst mit den Code-Tags ist das komplett unleserlich. Schon mal was von Quelltextformatierung gehört?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.