Python + minGW
Das ganze konnte ich nun doch nochmal effizienter machen, sodass ich hier nun keine Zeit mehr verschwende. Nun ist die Zeitaufteilung wiefolgt:drankaner hat geschrieben:@sirius3: Ich habe etwa drei Zeitfresser:
1. sind die Matrixmultiplikationen von oben ca. 40%,
2. Ist die Umrechnung in Kamerakoordinaten oben: calculatePointInCameraCoordSys.py diese benötigt etwa 35% der Zeit und
3. ist die Berechnung der möglichen Camerasettings (Also welche Kamera können mir zudem Punkt überhaupt einen Anteil liefern) ca 15%.
Die letzte Funktion hatte ich noch nicht gepostet.
Wobei diese, auch denk geringsten Zeitaufwand hat.Code: Alles auswählen
def combinations(objects, k): if objects == [] or len(objects) < k or k == 0: yield [] elif len(objects) == k: yield objects else: for combination in combinations(objects[1:], k-1): yield [objects[0]] + combination for combination in combinations(objects[1:], k): yield combination def Cameraset(validCams,validCamsNo,Cams): invalidCams=[] combs=list(combinations([0,1,2,3,4,5,6,7],validCamsNo)) #int(math.factorial(Cams)/(math.factorial(Cams-validCamsNo)*math.factorial(validCamsNo))) for x in range(0,len(validCams)): if validCams[x]==0: invalidCams.append(x) for y in range(0,len(invalidCams)): i=0 possible=len(combs) for x in range(0,possible): if combs[x-i].count(invalidCams[y])>0: combs.pop(x-i) i+=1 return combs
- 1. sind die Matrixmultiplikationen von oben ca. 50%,
2. Ist die Umrechnung in Kamerakoordinaten oben: calculatePointInCameraCoordSys.py diese benötigt etwa 45% der Zeit
Dann werd eich jetzt mal den Profiler duchlaufen lassen.
@drankaner: wie sieht denn jetzt Dein Code aus, und welche Zeilen brauchen wie lange?
»combinations« gibt es schon fertig in itertools, das braucht man nicht selbst zu schreiben. »Cameraset« und alle Variablennamen halten sich immer noch nicht an die üblichen Konventionen. Funktionen sollten nach einer Tätigkeit benannt sein. `Cams` wird gar nicht verwendet. Man iteriert direkt über Listen und baut sich neue, statt mit pop irgendwie die Liste zu verändern; das versteht nämlich niemand.
Nachdem ich raten konnte, was die unterschiedlichen Parameter bedeuten, kommt das dabei raus:
wobei man sich dann fragen muß, warum Du erst die Kombinationen aller Kameras erzeugst, um dann aus allen Kombinationen die ungültigen wieder zu entfernen und nicht gleich nur aus den Gültigen die Kombinationen erzeugst:
»combinations« gibt es schon fertig in itertools, das braucht man nicht selbst zu schreiben. »Cameraset« und alle Variablennamen halten sich immer noch nicht an die üblichen Konventionen. Funktionen sollten nach einer Tätigkeit benannt sein. `Cams` wird gar nicht verwendet. Man iteriert direkt über Listen und baut sich neue, statt mit pop irgendwie die Liste zu verändern; das versteht nämlich niemand.
Nachdem ich raten konnte, was die unterschiedlichen Parameter bedeuten, kommt das dabei raus:
Code: Alles auswählen
def find_cameraset_with_only_valid_cameras(cameras_validity, set_size):
combs = list(combinations(range(len(cameras_validity), set_size))
for num, valid in enumerate(cameras_validity):
if not valid:
combs = [c for c in combs if c.count(num) == 0]
return combs
Code: Alles auswählen
def find_cameraset_with_only_valid_cameras(cameras_validity, set_size):
valid_cameras = [num for num, valid in enumerate(cameras_validity) if valid]
return list(combinations(valid_cameras, set_size))
Genau an dem Punkt habe ich angegriffen und den Quatsch mit "pop" wieder rausgeschmissen. Hier muss ich auch gestehen, dass die Funktion erstmal Blind geschrieben habe (Hauptsache es funktioniert).Sirius3 hat geschrieben:@drankaner: wie sieht denn jetzt Dein Code aus, und welche Zeilen brauchen wie lange?
»combinations« gibt es schon fertig in itertools, das braucht man nicht selbst zu schreiben. »Cameraset« und alle Variablennamen halten sich immer noch nicht an die üblichen Konventionen. Funktionen sollten nach einer Tätigkeit benannt sein. `Cams` wird gar nicht verwendet. Man iteriert direkt über Listen und baut sich neue, statt mit pop irgendwie die Liste zu verändern; das versteht nämlich niemand.
Code: Alles auswählen
def find_valid_Cameraset(validCams,validCamsNo):
return list(combinations(validCams,validCamsNo))
8 Minuten für solveTriangulationLGS.py und 6-7 Minuten für calculatePointInCameraCoordSys.py.
Das die Variablen nicht der Konvention entsprechen, da stimme ich dir volkommen zu. Allerdings habe ich diese aus unserem tatsächlichen Programm das in C++ besteht (nicht von mir) übernommen und um später einfacher Sachen in dieses zu übernehmen habe diese bestehen lassen.
Nun ja mein
local_cs_in_global_vector übergibt einen Vektor der so aussehen kann:
[array([ 0.06999708, 0.68877751, -0.72814772]), array([ 0.68212451, 0.08660196, -0.7334991 ])] (Je nach Anzahl der Kameras, kommt jeweils noch eine Zeile hinzu)
local_tRefk_vector übergibt einen solchen Vektor:
[[1.45608435, -220.028403, 264.029949], [-219.686839, 0.265470325, 264.474263]] (Je nach Anzahl der Kameras, kommt jeweils noch eine Zeile hinzu)
Und x_iCamNo die Anzahl der gültigen Kameras.
Ich habe auch schon einmal anngepasst das local_cs_in_global_vector und local_tRefk_vector jeweils im richtigen Format ankommen, sodass ich numpy.asarray nicht benötige, daraufhin bin ich aber direkt langsamer geworden und zwar deutlich. (Finde ich unlogisch, war aber tatsächlich so)
@kbr: Folgendes kommt beim cProfiler raus (Ich habe mal nur die größten Punkte rausgenommen, aber anfangen kann ich damit nichts wirklich :/):
Nun ja mein
Ich habe den Code jetzt so angepasst.Sirius3 hat geschrieben:@drankaner: statt numpy.full nimmt man numpy.zeros. Welches Format haben denn local_cs_in_global_vector und local_tRefk_vector?
Ist x_iCamNo nicht einfach die Länge der Vektoren? Das braucht man dann nicht extra angeben.
Die ganzen asarray-Aufrufe sind in Deinem Fall überflüssig. Die Klammern bei den if und alle Strichpunkte sind das auch. Die einbuchstabigen Namen sind allesamt schlecht, weil sie nichts aussagen, für was sie stehen.
Die erste Hälfte ist vor allem mit dem `break` etwas seltsam, kann man aber bestimmt genauso zusammenfassen wie die zweite Hälfte, so dass es keine for-Schleifen mehr gibt:Code: Alles auswählen
s = x_pPoint3d - o s2 = (s**2).sum(axis=1) local = (r*s).sum(axis=1) local = s2 - local**2 * r2r maxsquaredist = local.max() meansquaredist = local.mean() return x_pPoint3d, maxsquaredist, meansquaredist
local_cs_in_global_vector übergibt einen Vektor der so aussehen kann:
[array([ 0.06999708, 0.68877751, -0.72814772]), array([ 0.68212451, 0.08660196, -0.7334991 ])] (Je nach Anzahl der Kameras, kommt jeweils noch eine Zeile hinzu)
local_tRefk_vector übergibt einen solchen Vektor:
[[1.45608435, -220.028403, 264.029949], [-219.686839, 0.265470325, 264.474263]] (Je nach Anzahl der Kameras, kommt jeweils noch eine Zeile hinzu)
Und x_iCamNo die Anzahl der gültigen Kameras.
Ich habe auch schon einmal anngepasst das local_cs_in_global_vector und local_tRefk_vector jeweils im richtigen Format ankommen, sodass ich numpy.asarray nicht benötige, daraufhin bin ich aber direkt langsamer geworden und zwar deutlich. (Finde ich unlogisch, war aber tatsächlich so)
Code: Alles auswählen
def solverTriangulationLGS(local_cs_in_global_vector, local_tRefk_vector,x_iCamNo):
a=numpy.zeros((3,3))
o=numpy.asarray(local_tRefk_vector)
r=numpy.asarray(local_cs_in_global_vector)
a[0,0]=x_iCamNo
a[1,1]=x_iCamNo
###Vorbereitung 3D Punkt
#r2r = Ein einzelner Wert, je Kamera existiert einer!
r2r=1/(r**2).sum(axis=1)
#local = Ein einzelner Wert, je Kamera existiert einer!
local=(r*o).sum(axis=1)
#r_2r = Ein 3er Vector, je Kamera existiert einer!
r_r2=(r.transpose()*r2r).transpose()
#b= ein 3er Vector
b = (o-(r_r2.transpose()*local).transpose()).sum(axis=0)
#a=eine 3x3 Matrix
a-=numpy.tensordot(r, r_r2, axes=[0,0])
a[2][2] = x_iCamNo * 2 - a[0][0] - a[1][1];
###3D Punkt berechnen
x_pPoint3d = numpy.matmul(numpy.linalg.inv(a),(b))
###Validierung des 3D Punkts
#s = Ein 3er Vector, je Kamera existiert einer!
s=x_pPoint3d-o
#s2 = Ein einzelner Wert, je Kamera existiert einer!
s2 = (s**2).sum(axis=1)
#local = Ein einzelner Wert, je Kamera existiert einer!
local = (r*s).sum(axis=1)
local = s2 - local*(local * r2r);
maxsquaredist=local.max()
sumsquaredist=local.mean()
return x_pPoint3d,maxsquaredist, sumsquaredist
Code: Alles auswählen
1 252,125 252,125 1309,809 1309,809 trangulation_batch.py:17(triangulation_batch)
35383040 81,419 0 81,419 0 {built-in method numpy.core.multiarray.array}
24840580 79,705 0 79,705 0 {method 'reduce' of 'numpy.ufunc' objects}
17639767 64,23 0 64,23 0 {built-in method numpy.core.multiarray.matmul}
35486513 26,408 0 26,408 0 {built-in method numpy.core.multiarray.zeros}
17743255 14,453 0 78,978 0 {method 'sum' of 'numpy.ndarray' objects}
58992005 10,06 0 10,06 0 {built-in method time.time}
10645953 9,351 0 9,351 0 {method 'reshape' of 'numpy.ndarray' objects}
21291906 9,039 0 9,039 0 {method 'transpose' of 'numpy.ndarray' objects}
3548656 8,684 0 8,684 0 {method 'astype' of 'numpy.ndarray' objects}
3548651 7,597 0 7,597 0 {built-in method numpy.core.multiarray.dot}
13086729 6,978 0 6,978 0 {built-in method numpy.core.multiarray.may_share_memory}
16637016 4,4 0 4,4 0 {built-in method builtins.hasattr}
28632953 3,764 0 3,764 0 {method 'append' of 'list' objects}
3548651 2,383 0 51,048 0 {method 'mean' of 'numpy.ndarray' objects}
7170593 2,278 0 2,283 0 {built-in method builtins.isinstance}
3548723 2,261 0 2,261 0 {built-in method builtins.max}
3548652 2,146 0 14,725 0 {method 'max' of 'numpy.ndarray' objects}
3551510 1,268 0 1,268 0 {built-in method builtins.iter}
3551908 1,169 0 1,169 0 {built-in method builtins.getattr}
3548733 1,09 0 1,09 0 {built-in method builtins.min}
3549617 1,039 0 1,04 0 {method 'get' of 'dict' objects}
3548651 0,785 0 0,785 0 {method '__array_prepare__' of 'numpy.ndarray' objects}
@drankaner: 35Mio Aufrufe dauern 81 Sekunden, die könnte man wahrscheinlich sparen, wenn man immer mit Numpy-Arrays arbeitet. Eine Liste von Arrays sieht daher komisch aus. Was dann aber nicht sein sollte, sind die vielen appends, die man nicht mit Numpy-Arrays machen sollte.
Dass Du solverTriangulationLGS 3,5Mio mal aufrufst, hast Du aber nicht gesagt, und in Deinem Profiler-Output fehlen auch alle Zeilen mit Deinen Python-Funktionen. Also bei dem Stückwerk und den ganzen Dingen, die Du verheimlichst, kann man Dir wirklich nicht helfen.
Dass Du solverTriangulationLGS 3,5Mio mal aufrufst, hast Du aber nicht gesagt, und in Deinem Profiler-Output fehlen auch alle Zeilen mit Deinen Python-Funktionen. Also bei dem Stückwerk und den ganzen Dingen, die Du verheimlichst, kann man Dir wirklich nicht helfen.