IRKamera: Unterschied zwischen den Versionen
Seck (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
(webroot hat sich geändert) |
||
(8 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
= IRKamera = |
|||
Ballerkennung mit Kamera OHNE IR-Filter (also Kamera nimmt sichtbares Licht sowie Licht im IR-Bereich auf) in Kombination mit IR-LED-Beleuchtung (sofern noetig) und einem Kickerball, der die entsprechende Wellenlängen reflektiert |
|||
== Uebersicht == |
|||
28.August 2008 |
28.August 2008 |
||
Zeile 7: | Zeile 11: | ||
Herr Menken/VRMagic hat vorgeschlagen die Ballerkennung so wie bei dem Wii Experiment über reflektieres Infrarotlicht zu machen. |
Herr Menken/VRMagic hat vorgeschlagen die Ballerkennung so wie bei dem Wii Experiment über reflektieres Infrarotlicht zu machen. |
||
Die Kamera, die wir leihweise bekommen werden, hat die Bezeichnung FC12 COB M12 mit 90 Grad Oeffnungswinkel. Dazu benötigen wir noch IR Leds die von der Kamera |
Die Kamera, die wir leihweise bekommen werden, hat die Bezeichnung FC12 COB M12 mit 90 Grad Oeffnungswinkel. Dazu benötigen wir noch IR Leds die von der Kamera getriggert und hinter der Kamera (Ring um das Objektiv) aufgestellt den mit 3M IR-retroreflekierendem Material beschichteten Ball anblitzen, der dann das IR-Licht hell reflektiert. Das lässt sich dann gut vorverarbeiten in einem quasi binären Bildmuster. |
||
IR Leds: |
IR Leds: |
||
[[Bild:hsdl4220.pdf]] |
[[Bild:hsdl4220.pdf]] |
||
[[Bild:sfh484_5_1.pdf]] |
|||
[[Bild:tsha440.pdf]] |
|||
== Vorhandene Hardware == |
|||
Geliefert wurde die Kamera VRmFC-12/BW COB M12 mit Objektiv (allerdings ohne IR-Filter), USB-Kabel und DevelopmentKit for Windows: |
|||
http://www.vrmagic.com/no_cache/de/vrmfc_12_bw_cob_m12/?camcolor=monochrome&camres=640x480&camfps=69 |
|||
* [752x480] 69 frames/s |
|||
* [640x480] 80 frames/s |
|||
* CMOS-Sensor: 1/3Zoll (= 8,47mm) |
|||
* Monochrom |
|||
* Auflösung: 752x480 |
|||
* Pixelgröße: 6x6 um |
|||
* FPS (bei max. Auflösung): 69 |
|||
* Pixeltakt: 5-26.6 MHz |
|||
* Shutter: global |
|||
* Platinenmaße (mm): 42x38x25 |
|||
* interner RAM: 64MB |
|||
* Beleuchtungsring optional möglich |
|||
== SDK fuer Linux == |
|||
http://www.vrmagic.com/de/downloads_img/ |
|||
== Schematischer Aufbau == |
|||
[[Bild:Aufbauskizze.png]] |
|||
Jede kamera hat einen Öffnungswinkel von etwa 87°. Sie werden jeweils in Verlängerung der Torauslinie seitlich am Kicker befestigt, so dass der Ball an jeder Position von beiden Kameras erfasst werden kann (durch einen 3mm-hohen Spalt in der Kicker-Außenwand), und aus dem aufgenommenen Bild der Winkel von der Kamera aus zum Ball extrahiert werden kann. |
|||
== Vorversuch der Ballberechnung == |
|||
Um zu prüfen, ob dieses Prinzip verwirklichbar ist, wurden verschiedene Ballpositionen simuliert und aus den daraus erhaltenen Winkel die Ballposition ermittelt. Um erste Einblicke ueber die Fehleranfaelligkeit zu erhalten, wurde die Genauigkeit der Winkel nach und nach verringert (eine Nachkommastelle, gar keine Nachkommastelle). |
|||
[[Bild:001-ball-rechts-unten.png]] |
|||
http://kicker.ee.hm.edu/wiki/images/002-ball-rechts-oben.png <br> |
|||
http://kicker.ee.hm.edu/wiki/images/003-ball-mitte-unten.png <br> |
|||
http://kicker.ee.hm.edu/wiki/images/004-ball-mitte-oben.png <br> |
|||
http://kicker.ee.hm.edu/wiki/images/005-ball-links-unten.png <br> |
|||
http://kicker.ee.hm.edu/wiki/images/006-ball-links-oben.png <br> |
|||
http://kicker.ee.hm.edu/wiki/images/007-ball-frei.png <br> |
|||
http://kicker.ee.hm.edu/wiki/images/008-ball-frei.png <br> |
|||
http://kicker.ee.hm.edu/wiki/images/009-ball-frei.png <br> |
|||
Sourcecode: |
|||
<source lang="cpp">#include <iostream> |
|||
#include <iomanip> // for setw() |
|||
#include <fstream> |
|||
#include <string> |
|||
#include <math.h> |
|||
using namespace std; |
|||
#define LINKS 0 |
|||
#define RECHTS 1 |
|||
//const double PI = 3.1415926535897932384626433832795; // besser M_PI benutzen |
|||
double Round(double Zahl, int Stellen) |
|||
{ |
|||
Zahl *= pow( 10, Stellen); |
|||
Zahl = floor(Zahl + 0.5); |
|||
Zahl *= pow(10, -Stellen); |
|||
return Zahl; |
|||
} |
|||
struct cam |
|||
{ |
|||
string name; |
|||
int x; |
|||
int y; |
|||
float angleCorrection; //Winkelkorrektur, rechte Kamera +90°, linke Kamera 3,33847° (== tan^-1(7/120) ) |
|||
}; |
|||
struct ballpos |
|||
{ |
|||
unsigned int nr; |
|||
float winkel1; |
|||
float winkel2; |
|||
unsigned int x; |
|||
unsigned int y; |
|||
float mBer1; //Berechnete Steigung, speaeter gleichsetzen der Geradengleichung y=m*x+t |
|||
float mBer2; //Berechnete Steigung Gerade von rechter Kamera durch den Ball |
|||
float xBer; //Berechnete x-Koordinate des Balls |
|||
float yBer; //Berechnete y-Koordinate des Balls |
|||
float fehler; //Fehler der berechneten Ballkoordinate (Pythagoras) |
|||
}; |
|||
int main() |
|||
{ |
|||
ifstream file("data.txt"); |
|||
cam cam[2]; |
|||
ballpos ballpos[9]; |
|||
string buffer, tmp; |
|||
//Werte aus Datei einlesen: |
|||
getline(file,buffer); // erste Zeile unwichtig |
|||
for(int i=0; i<2; i++) |
|||
{ |
|||
file >> cam[i].name; |
|||
file >> cam[i].x; |
|||
file >> cam[i].y; |
|||
file >> cam[i].angleCorrection; |
|||
getline(file,buffer); |
|||
} |
|||
getline(file,buffer); // Zeile unwichtig |
|||
for(int i=0; i<9; i++) |
|||
{ |
|||
file >> ballpos[i].nr; |
|||
file >> ballpos[i].winkel1; |
|||
file >> ballpos[i].winkel2; |
|||
// Opt. Winkel auf EINE Nachkommastelle runden, genauer wird man die Winkel nicht bestimmen koennen! |
|||
ballpos[i].winkel1 = Round(ballpos[i].winkel1,1); |
|||
ballpos[i].winkel2 = Round(ballpos[i].winkel2,1); |
|||
file >> ballpos[i].x; |
|||
file >> ballpos[i].y; |
|||
getline(file,buffer); |
|||
} |
|||
file.close(); |
|||
// Ueberpruefen, ob das Einlesen der Datei "data.txt" erfolgreich war: |
|||
cout << "Programm zur Positionsberechnung des Balles aus den Winkeln" << endl; |
|||
for(int i=0; i<2; i++) |
|||
cout << cam[i].name << ",\tx=" << cam[i].x << ",\ty=" << cam[i].y << ",\tWinkelkorrektur: " << cam[i].angleCorrection << endl; |
|||
for(int i=0; i<9; i++) |
|||
cout << ballpos[i].nr << ",\tw1=" << ballpos[i].winkel1 << ",\tw2=" << ballpos[i].winkel2 << ",\tx=" << ballpos[i].x << ",\ty=" << ballpos[i].y << endl; |
|||
cout << "Starten der Berechnung:" << endl; |
|||
for(int i=0; i<9; i++) |
|||
{ |
|||
ballpos[i].mBer1 = tan((ballpos[i].winkel1+cam[LINKS].angleCorrection )*M_PI/180); // Steigung von der linken Kamera aus |
|||
ballpos[i].mBer2 = tan((ballpos[i].winkel2+cam[RECHTS].angleCorrection)*M_PI/180); // Steigung von der rechten Kamera aus |
|||
ballpos[i].xBer = ( (-120*ballpos[i].mBer2)/(ballpos[i].mBer1-ballpos[i].mBer2) ); |
|||
ballpos[i].yBer = ballpos[i].mBer1 * ballpos[i].xBer -7; |
|||
ballpos[i].fehler = sqrt( pow(ballpos[i].xBer - ballpos[i].x, 2) + pow(ballpos[i].yBer - ballpos[i].y, 2) ); |
|||
cout << ballpos[i].nr << ", m1: " << setw(10) << ballpos[i].mBer1 << ", m2: " << setw(10) << ballpos[i].mBer2; |
|||
cout << ", x: " << setw(10) << ballpos[i].xBer << ", y: " << setw(10) << ballpos[i].yBer; |
|||
cout << ", Fehler: " << setw(13) << ballpos[i].fehler*10 << "mm" << endl; |
|||
} |
|||
return 0; |
|||
} |
|||
</source> |
|||
Dateiinhalt aus data.txt sowie erhaltene Resultate: |
|||
<source lang="text">Koordinaten Kameras (x y) + Korrektur in Grad |
|||
LeftCam 0 -7 3.33847 |
|||
RightCam 120 -7 90 |
|||
Winkel von den Kameras (Leftcam Rightcam) und Ballkoordinaten (x y) |
|||
001 1.0231 12.5288 118 2 |
|||
002 28.7541 1.54816 118 67 |
|||
003 5.1923 81.4692 60 2 |
|||
004 47.626 39.0355 60 67 |
|||
005 74.1327 85.6384 2 2 |
|||
006 85.1134 57.9074 2 67 |
|||
007 74.8591 57.704 14 60 |
|||
008 40.2976 61.9661 43 34 |
|||
009 2.93261 70.9744 91 3 |
|||
Ausgewertet (genaue Winkel): |
|||
1, m1: 0.0762711, m2: -4.5, x: 118, y: 1.99999, Fehler: 5.60284e-05mm |
|||
2, m1: 0.627118, m2: -36.9999, x: 118, y: 66.9999, Fehler: 0.000534058mm |
|||
3, m1: 0.15, m2: -0.150001, x: 60.0001, y: 2.00002, Fehler: 0.00108807mm |
|||
4, m1: 1.23333, m2: -1.23333, x: 60, y: 67, Fehler: 0.000351698mm |
|||
5, m1: 4.49999, m2: -0.0762717, x: 2.00002, y: 2.00006, Fehler: 0.00063763mm |
|||
6, m1: 37.0007, m2: -0.627119, x: 1.99996, y: 67.0001, Fehler: 0.000659088mm |
|||
7, m1: 4.78572, m2: -0.632076, x: 14, y: 60.0001, Fehler: 0.000615101mm |
|||
8, m1: 0.953488, m2: -0.532469, x: 43.0001, y: 34, Fehler: 0.000757196mm |
|||
9, m1: 0.10989, m2: -0.344827, x: 91, y: 3, Fehler: 0.000229489mm |
|||
Ausgewertet (Winkel auf EINE Nachkommastelle gerundet): |
|||
1, m1: 0.0758656, m2: -4.51071, x: 118.015, y: 1.95329, Fehler: 0.490912mm |
|||
2, m1: 0.628235, m2: -38.1885, x: 118.058, y: 67.168, Fehler: 1.7772mm |
|||
3, m1: 0.150137, m2: -0.149451, x: 59.8625, y: 1.98761, Fehler: 1.38047mm |
|||
4, m1: 1.23219, m2: -1.2349, x: 60.0659, y: 67.0125, Fehler: 0.670359mm |
|||
5, m1: 4.48789, m2: -0.0769458, x: 2.02274, y: 2.07786, Fehler: 0.81112mm |
|||
6, m1: 36.683, m2: -0.627299, x: 2.01756, y: 67.0102, Fehler: 0.20331mm |
|||
7, m1: 4.80284, m2: -0.632174, x: 13.9578, y: 60.0371, Fehler: 0.561781mm |
|||
8, m1: 0.953568, m2: -0.531709, x: 42.9584, y: 33.9638, Fehler: 0.551872mm |
|||
9, m1: 0.109314, m2: -0.344328, x: 91.0836, y: 2.95672, Fehler: 0.941122mm |
|||
Ausgewertet (Winkel auf GANZE Winkel gerundet): |
|||
1, m1: 0.0758656, m2: -4.33148, x: 117.934, y: 1.94717, Fehler: 0.842399mm |
|||
2, m1: 0.633114, m2: -28.6363, x: 117.404, y: 67.3303, Fehler: 6.81127mm |
|||
3, m1: 0.14657, m2: -0.158384, x: 62.3245, y: 2.1349, Fehler: 23.2841mm |
|||
4, m1: 1.24992, m2: -1.2349, x: 59.6372, y: 67.5419, Fehler: 6.52129mm |
|||
5, m1: 4.45128, m2: -0.0699268, x: 1.85597, y: 1.26144, Fehler: 7.52477mm |
|||
6, m1: 34.4741, m2: -0.624869, x: 2.13637, y: 66.6494, Fehler: 3.76217mm |
|||
7, m1: 4.8452, m2: -0.624869, x: 13.7081, y: 59.4185, Fehler: 6.50611mm |
|||
8, m1: 0.943621, m2: -0.531709, x: 43.248, y: 33.8097, Fehler: 3.12599mm |
|||
9, m1: 0.111081, m2: -0.344328, x: 90.7303, y: 3.07838, Fehler: 2.80901mm |
|||
</source> |
|||
== erste Aufnahmen == |
|||
Mit der Entwicklungsumgebung kann die Kamera schnell in Betrieb genommen und nach Belieben konfiguriert werden. Da die Kameras nur einen kleinen Spalt aufnehmen müssen, können sie auch mittels ROI (Region of Interrest) konfiguriert werden. Momentan nehmen sie beispielsweise ein Bild von 752x20px auf. Durch die dadurch veringerte Größe der Bildinformation kann die Bildrate auf über 100fps gesteigert werden (abhöngig von der Exposuretime). Mit einer exp. von 10ms können so 100fps realisiert werden. <br> <br> |
|||
Desweiteren kann mit diversen Filtereinstellungen (Gamma: 0.00, Luminance: 0, Contrast: 10, Blacklevel: je nach Lichtverhältnis angepasst) schon auf der Kamera eine Vorauswertung stattfinden (Ballpixel: weiß (0xff), sonst: schwart (0x00)). Dazu muss die Bande schwarz sein, um ein möglichst hohen Kontrast zu haben. <br> |
|||
Durch diese Vorauswertung bietet es sich außerdem an, mithilfe des auf der Kamera montierten FPGAs das Bild gleich in das RLE-Format umzuwandeln. Dabei werden die Bildinformationen in jeweils einem Byte-Päärchen gespeichert. Das erste Byte gibt die Farbe an (hier nur noch weiß oder schwarz), das zweite Byte die Anzahl der mit dieser Farbe folgenden Pixel (max. 255). Auf diese Weise reduziert sich zum einen die Datenmenge, die von der Kamera zum Hostrechner übertragen werden muss extrem, zum anderen wird so der erste Teil der Segmentierung (der einzelnen Zeilen) schon auf der Kamera durchgeführt und dadurch das Hostsystem entlastet. |
|||
== Inbetriebnahme zweier Kameras == |
|||
Die von VRmagic mitgelieferten Demoprogramme liefern einen guten Einstiegspunkt bei der Inbetriebnahme einer Kamera. Um die aufgenommenen Bilder live betrachten zu können wurde bei dem Democode "SDL-Viewer" die freie Multimedia-Bibliothek SDL (Simple DirectMedia Layer) verwendet. Dieser Beispielcode wurde nun soweit erweitert, dass zwei Kameras parallel verwendet werden können und verschiedene Parametereinstellungen über den Code durchgeführt werden können. Das Fenster zeigt neben den beiden Bildausschnitten der 2 Kameras auch ein Spielfeld, auf dem der Ball in der aktuell errechneten Position angezeigt wird (TODO: noch in Arbeit). |
Aktuelle Version vom 23. Dezember 2011, 14:08 Uhr
IRKamera
Ballerkennung mit Kamera OHNE IR-Filter (also Kamera nimmt sichtbares Licht sowie Licht im IR-Bereich auf) in Kombination mit IR-LED-Beleuchtung (sofern noetig) und einem Kickerball, der die entsprechende Wellenlängen reflektiert
Uebersicht
28.August 2008
Die Fa. VRmagic VRMagic stellt Framegrabber-lose Kameras her, die über USB2.0 an einen PC angeschlossen werden können und unter Windows XP/Vista aber auch unter Linux betrieben werden können. Der Vertrieb erfolgt über Stemmer-Elektronik Puchheim.
Preislich bewegen sich hier die Kameras zwischen 200 und 1200 Euro inkl. Software wohlgemerkt.
Herr Menken/VRMagic hat vorgeschlagen die Ballerkennung so wie bei dem Wii Experiment über reflektieres Infrarotlicht zu machen.
Die Kamera, die wir leihweise bekommen werden, hat die Bezeichnung FC12 COB M12 mit 90 Grad Oeffnungswinkel. Dazu benötigen wir noch IR Leds die von der Kamera getriggert und hinter der Kamera (Ring um das Objektiv) aufgestellt den mit 3M IR-retroreflekierendem Material beschichteten Ball anblitzen, der dann das IR-Licht hell reflektiert. Das lässt sich dann gut vorverarbeiten in einem quasi binären Bildmuster.
IR Leds:
Vorhandene Hardware
Geliefert wurde die Kamera VRmFC-12/BW COB M12 mit Objektiv (allerdings ohne IR-Filter), USB-Kabel und DevelopmentKit for Windows: http://www.vrmagic.com/no_cache/de/vrmfc_12_bw_cob_m12/?camcolor=monochrome&camres=640x480&camfps=69
* [752x480] 69 frames/s * [640x480] 80 frames/s
- CMOS-Sensor: 1/3Zoll (= 8,47mm)
- Monochrom
- Auflösung: 752x480
- Pixelgröße: 6x6 um
- FPS (bei max. Auflösung): 69
- Pixeltakt: 5-26.6 MHz
- Shutter: global
- Platinenmaße (mm): 42x38x25
- interner RAM: 64MB
- Beleuchtungsring optional möglich
SDK fuer Linux
http://www.vrmagic.com/de/downloads_img/
Schematischer Aufbau
Jede kamera hat einen Öffnungswinkel von etwa 87°. Sie werden jeweils in Verlängerung der Torauslinie seitlich am Kicker befestigt, so dass der Ball an jeder Position von beiden Kameras erfasst werden kann (durch einen 3mm-hohen Spalt in der Kicker-Außenwand), und aus dem aufgenommenen Bild der Winkel von der Kamera aus zum Ball extrahiert werden kann.
Vorversuch der Ballberechnung
Um zu prüfen, ob dieses Prinzip verwirklichbar ist, wurden verschiedene Ballpositionen simuliert und aus den daraus erhaltenen Winkel die Ballposition ermittelt. Um erste Einblicke ueber die Fehleranfaelligkeit zu erhalten, wurde die Genauigkeit der Winkel nach und nach verringert (eine Nachkommastelle, gar keine Nachkommastelle).
Sourcecode:
#include <iostream>
#include <iomanip> // for setw()
#include <fstream>
#include <string>
#include <math.h>
using namespace std;
#define LINKS 0
#define RECHTS 1
//const double PI = 3.1415926535897932384626433832795; // besser M_PI benutzen
double Round(double Zahl, int Stellen)
{
Zahl *= pow( 10, Stellen);
Zahl = floor(Zahl + 0.5);
Zahl *= pow(10, -Stellen);
return Zahl;
}
struct cam
{
string name;
int x;
int y;
float angleCorrection; //Winkelkorrektur, rechte Kamera +90°, linke Kamera 3,33847° (== tan^-1(7/120) )
};
struct ballpos
{
unsigned int nr;
float winkel1;
float winkel2;
unsigned int x;
unsigned int y;
float mBer1; //Berechnete Steigung, speaeter gleichsetzen der Geradengleichung y=m*x+t
float mBer2; //Berechnete Steigung Gerade von rechter Kamera durch den Ball
float xBer; //Berechnete x-Koordinate des Balls
float yBer; //Berechnete y-Koordinate des Balls
float fehler; //Fehler der berechneten Ballkoordinate (Pythagoras)
};
int main()
{
ifstream file("data.txt");
cam cam[2];
ballpos ballpos[9];
string buffer, tmp;
//Werte aus Datei einlesen:
getline(file,buffer); // erste Zeile unwichtig
for(int i=0; i<2; i++)
{
file >> cam[i].name;
file >> cam[i].x;
file >> cam[i].y;
file >> cam[i].angleCorrection;
getline(file,buffer);
}
getline(file,buffer); // Zeile unwichtig
for(int i=0; i<9; i++)
{
file >> ballpos[i].nr;
file >> ballpos[i].winkel1;
file >> ballpos[i].winkel2;
// Opt. Winkel auf EINE Nachkommastelle runden, genauer wird man die Winkel nicht bestimmen koennen!
ballpos[i].winkel1 = Round(ballpos[i].winkel1,1);
ballpos[i].winkel2 = Round(ballpos[i].winkel2,1);
file >> ballpos[i].x;
file >> ballpos[i].y;
getline(file,buffer);
}
file.close();
// Ueberpruefen, ob das Einlesen der Datei "data.txt" erfolgreich war:
cout << "Programm zur Positionsberechnung des Balles aus den Winkeln" << endl;
for(int i=0; i<2; i++)
cout << cam[i].name << ",\tx=" << cam[i].x << ",\ty=" << cam[i].y << ",\tWinkelkorrektur: " << cam[i].angleCorrection << endl;
for(int i=0; i<9; i++)
cout << ballpos[i].nr << ",\tw1=" << ballpos[i].winkel1 << ",\tw2=" << ballpos[i].winkel2 << ",\tx=" << ballpos[i].x << ",\ty=" << ballpos[i].y << endl;
cout << "Starten der Berechnung:" << endl;
for(int i=0; i<9; i++)
{
ballpos[i].mBer1 = tan((ballpos[i].winkel1+cam[LINKS].angleCorrection )*M_PI/180); // Steigung von der linken Kamera aus
ballpos[i].mBer2 = tan((ballpos[i].winkel2+cam[RECHTS].angleCorrection)*M_PI/180); // Steigung von der rechten Kamera aus
ballpos[i].xBer = ( (-120*ballpos[i].mBer2)/(ballpos[i].mBer1-ballpos[i].mBer2) );
ballpos[i].yBer = ballpos[i].mBer1 * ballpos[i].xBer -7;
ballpos[i].fehler = sqrt( pow(ballpos[i].xBer - ballpos[i].x, 2) + pow(ballpos[i].yBer - ballpos[i].y, 2) );
cout << ballpos[i].nr << ", m1: " << setw(10) << ballpos[i].mBer1 << ", m2: " << setw(10) << ballpos[i].mBer2;
cout << ", x: " << setw(10) << ballpos[i].xBer << ", y: " << setw(10) << ballpos[i].yBer;
cout << ", Fehler: " << setw(13) << ballpos[i].fehler*10 << "mm" << endl;
}
return 0;
}
Dateiinhalt aus data.txt sowie erhaltene Resultate:
Koordinaten Kameras (x y) + Korrektur in Grad
LeftCam 0 -7 3.33847
RightCam 120 -7 90
Winkel von den Kameras (Leftcam Rightcam) und Ballkoordinaten (x y)
001 1.0231 12.5288 118 2
002 28.7541 1.54816 118 67
003 5.1923 81.4692 60 2
004 47.626 39.0355 60 67
005 74.1327 85.6384 2 2
006 85.1134 57.9074 2 67
007 74.8591 57.704 14 60
008 40.2976 61.9661 43 34
009 2.93261 70.9744 91 3
Ausgewertet (genaue Winkel):
1, m1: 0.0762711, m2: -4.5, x: 118, y: 1.99999, Fehler: 5.60284e-05mm
2, m1: 0.627118, m2: -36.9999, x: 118, y: 66.9999, Fehler: 0.000534058mm
3, m1: 0.15, m2: -0.150001, x: 60.0001, y: 2.00002, Fehler: 0.00108807mm
4, m1: 1.23333, m2: -1.23333, x: 60, y: 67, Fehler: 0.000351698mm
5, m1: 4.49999, m2: -0.0762717, x: 2.00002, y: 2.00006, Fehler: 0.00063763mm
6, m1: 37.0007, m2: -0.627119, x: 1.99996, y: 67.0001, Fehler: 0.000659088mm
7, m1: 4.78572, m2: -0.632076, x: 14, y: 60.0001, Fehler: 0.000615101mm
8, m1: 0.953488, m2: -0.532469, x: 43.0001, y: 34, Fehler: 0.000757196mm
9, m1: 0.10989, m2: -0.344827, x: 91, y: 3, Fehler: 0.000229489mm
Ausgewertet (Winkel auf EINE Nachkommastelle gerundet):
1, m1: 0.0758656, m2: -4.51071, x: 118.015, y: 1.95329, Fehler: 0.490912mm
2, m1: 0.628235, m2: -38.1885, x: 118.058, y: 67.168, Fehler: 1.7772mm
3, m1: 0.150137, m2: -0.149451, x: 59.8625, y: 1.98761, Fehler: 1.38047mm
4, m1: 1.23219, m2: -1.2349, x: 60.0659, y: 67.0125, Fehler: 0.670359mm
5, m1: 4.48789, m2: -0.0769458, x: 2.02274, y: 2.07786, Fehler: 0.81112mm
6, m1: 36.683, m2: -0.627299, x: 2.01756, y: 67.0102, Fehler: 0.20331mm
7, m1: 4.80284, m2: -0.632174, x: 13.9578, y: 60.0371, Fehler: 0.561781mm
8, m1: 0.953568, m2: -0.531709, x: 42.9584, y: 33.9638, Fehler: 0.551872mm
9, m1: 0.109314, m2: -0.344328, x: 91.0836, y: 2.95672, Fehler: 0.941122mm
Ausgewertet (Winkel auf GANZE Winkel gerundet):
1, m1: 0.0758656, m2: -4.33148, x: 117.934, y: 1.94717, Fehler: 0.842399mm
2, m1: 0.633114, m2: -28.6363, x: 117.404, y: 67.3303, Fehler: 6.81127mm
3, m1: 0.14657, m2: -0.158384, x: 62.3245, y: 2.1349, Fehler: 23.2841mm
4, m1: 1.24992, m2: -1.2349, x: 59.6372, y: 67.5419, Fehler: 6.52129mm
5, m1: 4.45128, m2: -0.0699268, x: 1.85597, y: 1.26144, Fehler: 7.52477mm
6, m1: 34.4741, m2: -0.624869, x: 2.13637, y: 66.6494, Fehler: 3.76217mm
7, m1: 4.8452, m2: -0.624869, x: 13.7081, y: 59.4185, Fehler: 6.50611mm
8, m1: 0.943621, m2: -0.531709, x: 43.248, y: 33.8097, Fehler: 3.12599mm
9, m1: 0.111081, m2: -0.344328, x: 90.7303, y: 3.07838, Fehler: 2.80901mm
erste Aufnahmen
Mit der Entwicklungsumgebung kann die Kamera schnell in Betrieb genommen und nach Belieben konfiguriert werden. Da die Kameras nur einen kleinen Spalt aufnehmen müssen, können sie auch mittels ROI (Region of Interrest) konfiguriert werden. Momentan nehmen sie beispielsweise ein Bild von 752x20px auf. Durch die dadurch veringerte Größe der Bildinformation kann die Bildrate auf über 100fps gesteigert werden (abhöngig von der Exposuretime). Mit einer exp. von 10ms können so 100fps realisiert werden.
Desweiteren kann mit diversen Filtereinstellungen (Gamma: 0.00, Luminance: 0, Contrast: 10, Blacklevel: je nach Lichtverhältnis angepasst) schon auf der Kamera eine Vorauswertung stattfinden (Ballpixel: weiß (0xff), sonst: schwart (0x00)). Dazu muss die Bande schwarz sein, um ein möglichst hohen Kontrast zu haben.
Durch diese Vorauswertung bietet es sich außerdem an, mithilfe des auf der Kamera montierten FPGAs das Bild gleich in das RLE-Format umzuwandeln. Dabei werden die Bildinformationen in jeweils einem Byte-Päärchen gespeichert. Das erste Byte gibt die Farbe an (hier nur noch weiß oder schwarz), das zweite Byte die Anzahl der mit dieser Farbe folgenden Pixel (max. 255). Auf diese Weise reduziert sich zum einen die Datenmenge, die von der Kamera zum Hostrechner übertragen werden muss extrem, zum anderen wird so der erste Teil der Segmentierung (der einzelnen Zeilen) schon auf der Kamera durchgeführt und dadurch das Hostsystem entlastet.
Inbetriebnahme zweier Kameras
Die von VRmagic mitgelieferten Demoprogramme liefern einen guten Einstiegspunkt bei der Inbetriebnahme einer Kamera. Um die aufgenommenen Bilder live betrachten zu können wurde bei dem Democode "SDL-Viewer" die freie Multimedia-Bibliothek SDL (Simple DirectMedia Layer) verwendet. Dieser Beispielcode wurde nun soweit erweitert, dass zwei Kameras parallel verwendet werden können und verschiedene Parametereinstellungen über den Code durchgeführt werden können. Das Fenster zeigt neben den beiden Bildausschnitten der 2 Kameras auch ein Spielfeld, auf dem der Ball in der aktuell errechneten Position angezeigt wird (TODO: noch in Arbeit).