Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!
Wonach ich nun gestern einmal doch ein Programm ausprobiertze, dass mit einem moving Average arbeitete, da aber wirklich keine schönen Bilder herauskamen, bin ich doch wieder dazu übergegangen die normale Lösung anzugehen.
Zitat:inc(pBR,BRows*YLenF);
pBC:=pBR;
// pBR: Pointer auf nächste Zeile! Eine Zeile ist YLenF hoch und BRows breit.
end;
Ich gehe gerade durch dein Programm und versuche es nachzuvollziehen, allerdings habe ich an der oben zitierten Stelle ein Problem. Müßte es da nicht eher heißen: inc(pBR,BCols*YLenF); schließlich wollen wir in die nächste Zeile springen und eine Zeilenlänge wird doch gerade durch die Anzahl der Kolumnen vorgegeben. Der Teil dp:=(BCols-YLenF-1); soll ja auch einen Zeilenvorsprung bewirken und dort rechnen wir auch mit BCols. allerdings hätte ich dann auch:
MRows:= (BRows div XLenF);
MCols:= (BCols div YLenF);
eher als folgendes geschrieben:
MRows:= (BRows div YLenF);
MCols:= (BCols div XLenF);
Diese Sache bereitet mir gerade noch größeres Kopfzerbrechen.
' schrieb:Ich gehe gerade durch dein Programm und versuche es nachzuvollziehen, allerdings habe ich an der oben zitierten Stelle ein Problem. Müßte es da nicht eher heißen: inc(pBR,BCols*YLenF); schließlich wollen wir in die nächste Zeile springen und eine Zeilenlänge wird doch gerade durch die Anzahl der Kolumnen vorgegeben. Der Teil dp:=(BCols-YLenF-1); soll ja auch einen Zeilenvorsprung bewirken und dort rechnen wir auch mit BCols. allerdings hätte ich dann auch:
MRows:= (BRows div XLenF);
MCols:= (BCols div YLenF);
Du hast natürlich Recht!
Ich hab wieder mal Spalte und Reihe verwechselt. Einigen wird uns auf folgendes: Spalte (also Col) ist das, was rüberwärts geht, also X-Richtung. Reihe (also Row) ist das, was runterwärts geht, also Y-Richtung. Demzufolge steht bei allem mit Row immer X und bei allem mit Col immer Y. Dann müsste aber auch zuerst die Y-Schleife kommen, da kann ich dann besser denken. Die X-Schleife wäre dann innen, was zur Folge hat, erst "die ganze erste Zeile (= Reihe = Row)" dann "die ganze zweite Zeile" etc. Damit sieht das "2D-Array" im Speicher dann wie folgt aus: Alle X-Werte der ersten Zeile, alle X-Werte der zweiten Zeile etc. Das wiederum ist wichtig für das spätere daterstellen.
Die Frage ist dann natürlich: Wie kommen die Daten (Bild[]) herein: Alle X hintereinander oder alle Y hintereinander?
Code:
inc(pBR,BRows*YLenF);
Dieses ist aber richtig: Row ist die X-Richtung, YLenF die Y-Richtung. Hiermit werden als YLenF-Zeilen übersprungen!
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Zitat:Einigen wird uns auf folgendes: Spalte (also Col) ist das, was rüberwärts geht, also X-Richtung. Reihe (also Row) ist das, was runterwärts geht, also Y-Richtung.
inc(pBR,BRows*YLenF);
Dieses ist aber richtig: Row ist die X-Richtung, YLenF die Y-Richtung. Hiermit werden als YLenF-Zeilen übersprungen!
Also nun bin ich vollkommen verwirrt. Ich sehe das immer so, dass die Horizontale, x-Richtung, die Reihen sind aber eben egrade durch Cols beschrieben werden, zB 30 Kolumnen, ergeibt eine Reihenlänge von 30. Leider sehe ich erst am Ende wie das nun heraus und hereinwandert, gehe aber davon aus, dass zuerst die Erste Reihe hereinkommt, dann die Zweite dahinter gehangen wird usw. Wenn das am Ende dann doch nach Kolumen geht, ist das natürlich tragisch.
Ich habe nun auf deiner Delphi Grundlage mal versucht das Programm in C zu schreiben, leider erhalte ich damit wieder eine Fehlermeldung seitens LV, dass er die LLB nicht aufrufen könnte, bzw einmal auch, dass er außerhalb des Heaps etwas versuchen würde zu schreiben.
Ich vermute, dass das unter anderem daran versuchen könnte, wie ich die Zeiger auf ihre Startadresse setze, bzw einen Zeiger auf das erstellte MeanIm Array setze:
' schrieb:Also nun bin ich vollkommen verwirrt. Ich sehe das immer so, dass die Horizontale, x-Richtung, die Reihen sind aber eben egrade durch Cols beschrieben werden, zB 30 Kolumnen, ergeibt eine Reihenlänge von 30. Leider sehe ich erst am Ende wie das nun heraus und hereinwandert, gehe aber davon aus, dass zuerst die Erste Reihe hereinkommt, dann die Zweite dahinter gehangen wird usw.
Ja, das ist ja immer der Mist. Ständig muss ich da drüber grübeln, was jetzt wie in welcher Reihenfolge kommt. Aber eigentlich ist das nicht so schlimm: Wichtig ist nur, dass der Algorithmus "konstistent" ist. D.h. man überlegt es sich zuerst bildlich im Geiste wie es sein soll: Zuerst Pointer auf Null. Dann alle Fenster rüberwärts. Dann Pointer auf den Beginn der soundsovielste Zeile (= begin der Reihe). Dann wieder rüberwärts. etc. Dann benutzt man ein Bild, von dem man das genaue Ergebnis kennt. Hat man die falsche Richtung genommen, ist das Ergebnis gespiegelt. Jetzt muss man lediglich Row und Col austauschen - uns schon MUSS es funktionieren. (Leider hab ich zu wenig Zeit das genau auszuprobieren. Auch mangelt es mir an einem entsprechendem Bild). "bildlich im Geiste" kann auch heißen: Stift und Papier nehmen und aufzeichnen.
Zitat:Wenn das am Ende dann doch nach Kolumen geht, ist das natürlich tragisch.
Tragisch ist das nicht. Durch vertauschen von Col/Row muss dieses Problem zu lösen sein.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Das ist ein ganz böser Fehler.
Da hiermit ein Zugriff in der Art "Sum += (int)*BildP" stattfindet, wird das garantiert eine Zugriffsverletzung geben. Du greifst damit auf die Adresse 0 im Datensegment zu. Du willst aber nicht auf 0 zugreifen, sondern auf den Start des Bildarrays. 0 ist zwar der relative Start im Bildarray, tatsächlich zugreifen musst du aber auf eine absolute Adresse im Datensegment. Und die ist nunmal das da: "BildP = (*Bild)->arg1;" (davon gehe ich aus. Ob es tatsächlich so ist, weiß ich nicht. Würdest du die Daten per "Zeiger auf Daten" an die DLL übergeben, Wäre genau dieser Zeiger der Wert von BildP).
"Sum += (int)*BildP" ist auch noch doppelt-doppelt-gemoppelt: Sum und *BildP sind - laut Definition - double. Da nützt dir das (int) gar nichts. Der Kompiler macht trotzdem wieder double draus. Und außerdem: Sind die Bilddaten nicht in U8? Dann muss *BildP aber U8 sein!
Code:
MeanImP=&MeanIm[0];
Das ist nicht ganz falsch - aber auch nicht richtig.
Du hast MeanImP als 2D-Array angelegt. Und das auch noch in kompliziertester Form. &MeanIm[0] ist NICHT ein Pointer auf Datenspeicher, sondern ein Pointer auf einen Pointer auf Datenspeicher (double ** MeanIm
Wenn ich das richtig verstanden habe, generierst du mit callocmatrix nämlich soviele Pointer wie die Matrix Spalten hat. Warum erzeugst du ein so kompliziertes Array, wenn du dann sowieso nur mit MeanImP++ darauf zugreifst? Mach halt ein 1D-Array "calloc(Länge*Breite)".
[*grübel*]
Mit dem Datentyp "double ** MeanIm;" kannst du NICHT mittels MeanImP++ oder ähnlich von einer Zeile auf die nächste springen. Der Zeiger auf die Erste Zeile steht in MeanIm[0]. Der Zeiger auf die Zweite Zeile steht in MeanIm[1]. Also: Poiner auf Zeil X steht in MeanIm[X-1]; Willst du jetzt also von Zeile Eins zur Zeile zwei musst du den Pointer aus MeanIm[1] auslesen. Mit anderen Worten: Es ist nicht zwingend gesagt, dass in einem Array double** die Daten hintereinander stehen!
Code:
MeanImP=&MeanIm[0];
MeanImP=0;
Wieso machst du hier beide Zuweisungen? Die letztere ist auf jeden Fall falsch. Auch das mit KontrastP=0 ist falsch.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Also ich habe es nun einmal ausprobiert indem ich einfach ein 1D Array für MeanIm anlegte aber das wollte immernoch nicht funktionieren, allerdings hängt es wohl wirklich an diesem Array.
Mittleerweile habe ich aber auch einmal eine Version mit expliziten Array Zugriffen ans laufen bekommen, das ist nun ca 45ms schnell oder langsam, je nachdem wie man es sieht. Daher würde es mich schon reuzen, dass ganz mit den selbstinkrementierenden Zeigern mal hin zu bekommen und zu sehen wie viel schneller es dadurch dann noch wird. Leider erlaubt es mir die Zeit gerade nicht daran kontinuierlich weiterzuarbeiten aber ich hoffe, dass es demnächst wieder etwas besser aussieht und ich auch das mal hin bekomme, wenngleich es mich auch schon einiges an Nerven gekostet hat.. irgendwie will es mit den selbstinkrementierenden Zeigern einfach nicht funktionieren wenn ich den speicher für dieses MeanIm Array selbst allkokiere. Ich versuchte auch einmal das dann einfach in LV anzulegen und zu übergeben -was halbwegs funktionierte aber dafür sorgte, dass die Geschwindigkeit nun ganz und gar nicht mehr annehmbar war.