Berechnung der Zernike Koeffizienten

Neue Frage »

beecksche Auf diesen Beitrag antworten »
Berechnung der Zernike Koeffizienten
Hi,

ich habe eine Punktwolke und möchte diese Fläche mithilfe von Zernike Polynomen beschreiben. Die Punkte sind in Polarkoordinaten in einem array gespeichert.

die Zernike Koeffizienten könnten mithilfe



brechnet werden.

Ich interpretieren das Doppelintegral als zwei Summen:



Mein Source Code sieht dabei folgendermaßen aus:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
void calculateZernikeCoefficients()
{
  int maxTerm = 45;

  int dp = 6;
  int dr = 10;

  std::vector<double> coeffs;

  for (int j = 0; j <= maxTerm ; j++){
	  double sum = 0;

	  for (int r = 0; r <= 1000; r += dr) { // äußere Integral
		  double rho = r / 1000.0;

		  for (int phi = 0; phi < 360.0; phi += dp) { // innere Integral
			  sum += (surfacePoint(phi, r) * zernikePolynom(j, rho, phi) * rho * dr * dp);
		  }
	  }
	  coeffs << (sum  / M_PI);
  }
}


Die Koeffizienten die ich erhalte, sind jedoch nicht brauchbar.

Ist meine Interpretation korrekt?
beecksche Auf diesen Beitrag antworten »

Hi da ich meine Beitrag leider nicht mehr editieren kann:

Die Koeffizienten scheinen mir jedoch nicht wirklich das zu sein, was ich erwarte.
Hier das coeffs-array (OSA Notation):
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
		[0]	980700.19465775450	double
		[1]	-3.1288742018393809e-011	double
		[2]	-5.1549299413273937e-011	double
		[3]	2.0274127761521041e-011	double
		[4]	555774.88048920350	double
		[5]	-1.0313478647092364e-010	double
		[6]	1.2471166942997213e-010	double
		[7]	-4.3470407806384921e-012	double
		[8]	-1.1797172066498634e-011	double
		[9]	1.4004618373420157e-011	double
		[10]	5.0383854975442320e-005	double
		[11]	-1.7958118521472230e-012	double
		[12]	-6636.4050724727849	double
		[13]	7.5994053189101630e-013	double
		[14]	0.00048910696966268565	double
		[15]	-3.0035744831883025e-012	double
		[16]	-1.7867649410532823e-011	double
		[17]	-2.5105178285685360e-012	double
		[18]	-2.7864486169337262e-012	double
		[19]	-3.3654509269459292e-012	double
		[20]	-2.3731857181625164e-010	double
		[21]	-4.1326289877120981e-011	double
		[22]	-5.3211443787291965e-005	double
		[23]	-1.3389428419032191e-012	double
		[24]	1351.8525378700701	double
		[25]	4.7043937688491480e-013	double
		[26]	-0.00015293021312349733	double
		[27]	1.0935906130355482e-010	double
		[28]	-1.0052927607586873e-010	double
		[29]	-2.3341030622366929e-012	double
		[30]	8.9021605164376196e-012	double
		[31]	1.6917723745669052e-012	double
		[32]	2.8588239056852519e-012	double
		[33]	7.9612817626677896e-013	double
		[34]	7.7007307231622983e-011	double
		[35]	7.7622497186010947e-011	double
		[36]	0.00091138658481068255	double
		[37]	1.6592034946287188e-011	double
		[38]	-0.00025437104320504689	double
		[39]	1.4565526861244479e-012	double
		[40]	260.91664049136887	double
		[41]	2.5331351063033878e-013	double
		[42]	-0.00073176084779277698	double
		[43]	-4.2050042764636237e-011	double
		[44]	-0.0012065249209630587	double
		[45]	4.7507139536501248e-010	double


Bei der Fläche W handelt es sich um eine rotationssymmetrische Freiformfläche mit

.

Demnach sollte ich bei den Zernike Koeffizienten kein Offset erhalten, also . Dies is leider NICHT der Fall.

Das gute ist, dass alle Koeffizienten außer die sphärischen Terme (4, 12, ...) gleich null sind.
Steffen Bühler Auf diesen Beitrag antworten »
RE: Berechnung der Zernike Koeffizienten
Die Berechnung erscheint mir vom Prinzip her in Ordnung. Nur ein paar Anmerkungen zum Code:

code:
1:
2:
3:
	  for (int r = 0; r <= 1000; r += dr) { // äußere Integral


Hier lässt Du r von 0 bis 1000 laufen, berechnest also nicht 1000, sondern 1001 Elemente. Das ist eigentlich 1 zuviel, außerdem habe ich Bedenken, ob surfacePoint(phi, 1000) überhaupt definiert ist. Auch wundert mich die unorthodoxe Definition mit dem Winkel als ersten Parameter, aber das ist natürlich Geschmackssache der Programmierers.

Auch dass der Winkel im Gradmaß verwendet wird, ist zumindest auffällig. Bei surfacePoint(phi, r) mag er ja vielleicht als Index dienen, der dann allerdings in Sechserschritten inkrementiert wird, was auch ungewöhnlich wäre. Aber spätestens bei zernikePolynom(j, rho, phi) würde ich mich noch mal vergewissern, dass dort kein Bogenmaß erwartet wird.

Viele Grüße
Steffen
beecksche Auf diesen Beitrag antworten »
RE: Berechnung der Zernike Koeffizienten
Dank für die schnelle Antwort.

Der eigentliche source code sieht etwas anders aus.

Ich habe die Konvertierung von Grad in Bogenmaß entfernt, um die Funktion etwas anschaulicher zu machen.

Bei den Funktion surfacePoint() und zernikePolynom() kann ich mir eigentlich sicher sein, dass diese korrekt sind, da ich sie in anderen Teilen ebenso verwende.
HAL 9000 Auf diesen Beitrag antworten »
RE: Berechnung der Zernike Koeffizienten
Zitat:
Original von beecksche
Ich habe die Konvertierung von Grad in Bogenmaß entfernt, um die Funktion etwas anschaulicher zu machen.

Tja, und wer weiß was du sonst noch entfernt hast, und irgendwo dort in diesen undurchsichtigen Skalierungen wird der Fehler stecken.

Z.B. entspricht deine Laufvariable ja nicht dem , allem Anschein nach ist und demzufolge auch , bei dir allem Anschein nach mit festem .

Die Multiplikation mit dr macht also die Integralsumme um den Faktor R=1000 zu groß.
beecksche Auf diesen Beitrag antworten »
RE: Berechnung der Zernike Koeffizienten
Da hast du recht, war blöd von mir.
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
void calculateZernikeCoefficients()
{
  int maxTerm = 45;

  int dp = 6;
  int dr = 10;

  std::vector<double> coeffs;
  double dRho = dr / 1000.0;
  double dPhi = degreeInRad(dp);

  for (int n = 0; n <= nMax; n++)
  {
	double sum = 0;

	for (int r = 0; r <= 1000; r += dr)
	{
		double rho = r / 1000.0;

		for (int phi = 0; phi < 360.0; phi += dp)
		{
			double phiInRad = degreeInRad(phi);
			double w = surfacePoint(phi / 360.0, rho);

			double z =zernikePolynom(n, rho, phiInRad);

			sum += (w * z * rho * dRho * dPhi);
		}
	}

	coeffs << (sum  / M_PI);

  }
}


Hinter der surfacePoint Funktion verbirgt sich eine NURBS Fläche mit .
 
 
Steffen Bühler Auf diesen Beitrag antworten »
RE: Berechnung der Zernike Koeffizienten
Zitat:
Original von beecksche
Hinter der surfacePoint Funktion verbirgt sich eine NURBS Fläche


Und die hat den Mittelwert Null, wie Du schreibst. Ich würde jetzt mal prüfen, ob das auch herauskommt: also mal den Zernike fest auf Eins setzen und den Null-Koeffizienten berechnen, der dann Null sein muss.
beecksche Auf diesen Beitrag antworten »

Dank für eure ganzen Antworten und Hilfestellungen.

Ich habe einen Denkfehler bei meiner Annahme des Offsets gemacht. Der Offset muss und kann in meinem Fall nicht 0 sein.

Ich habe die Koeffizienten berechnet und daraus wieder die Fläche generiert. Es passt alles wunderbar! Dankesehr!
Neue Frage »
Antworten »



Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »