AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Abstand (min, max, avg) in Bitmap

Ein Thema von cltom · begonnen am 12. Dez 2011 · letzter Beitrag vom 14. Dez 2011
Antwort Antwort
cltom

Registriert seit: 22. Sep 2005
221 Beiträge
 
Delphi 12 Athens
 
#1

Abstand (min, max, avg) in Bitmap

  Alt 12. Dez 2011, 14:45
Hallo,

folgende, nicht ganz leicht zu erklärende, Problemstellung:

Ich habe eine (monochrome) Bitmap mit verschiedenen Elementen, im einfachsten Fall ein paar verteilte Punkte (schwarz). Was ich nun brauche ist der mittlere (maximale und minimale) Abstand jedes (weissen) Pixels zum nächstgelegenen (schwarzen) Punkt.

In erster Näherung könnte ich für jeden (weissen) Punkt der Bitmap alle anderen Punkte der Bitmap durchgehen und prüfen, ob der Punkt a) schwarz ist, wenn ja b) den Abstand ermitteln. Wenn der untersuchte Punkt selbst schwarz ist, dann gilt Abstand=0

Der Aufwand dafür beträgt aber (bitmap.height * bitmap.width)² Durchläufe. Bei 1 MP sind das also 10^12 Durchläufe. Bei hohem Anteil (schwarzer) Punkte sinkt der Aufwand natürlich, aber dennoch ,der Aufwand erscheint groß. Bevor ich aber diese Brute-Force-Methode mache, frage ich mal:

Hat jemand eine klügere Idee?

Ein Ansatz wäre, nur ein Gitter von jedem x. Pixel zu verwerten, den Fehler könnte man versuchen, mit variierendem x abzuschätzen. Aber letztlich ist das nur "less brute".

Würde die Kenntnis der Koordinaten der `(schwarzen) Punkte etwas bringen?

danke für Tipps
grüße
tom
  Mit Zitat antworten Zitat
KarstenK

Registriert seit: 4. Dez 2007
Ort: Bärenthal
29 Beiträge
 
Delphi 2009 Enterprise
 
#2

AW: Abstand (min, max, avg) in Bitmap

  Alt 12. Dez 2011, 15:17
Hallo,

Erosion und Dilatation wäre hier eine Variante.

Die Operation iterative solange durchführen, bis keine weissen Punkte mehr da sind. und in jeden Stufe die Pixel welche wegfallen mit der Schrittweite kodieren. Damit erhälts du dannn eine Landkarte mit den (minimalen) Abständen.
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#3

AW: Abstand (min, max, avg) in Bitmap

  Alt 13. Dez 2011, 06:59
Du musst ja nicht jedesmal, wenn Du einen Punkt analysierst, die ganze Bitmap durchgehen.

1. Ermitteln der Positionen aller Punkte und aufteilen in Schwarz/Weiß.
2. Ermitteln aller Abstände zwischen zwei Punkten (weiss ->schwarz)
3. Ermitteln der Zielwerte Min/Max/Avg für jeden weissen Punkt

Erster Durchlauf: O(h*b). h,b = Dimension des Bitmaps.
Zweiter und dritter Durchlauf: O(n*m). n= Anzahl der gefundenen weissen Punkte, m=schwarze Punkte

Ist n*m überschaubar, gehts eins-fix-drei, Im theoretischen Worstcase jedoch O((h*b)^2). Die Frage lautet jedoch: Was ist der realistische Worstcase?

Selbst bei einigen Tausend Punkten solltest Du in überschaubarer Zeit hinkommen.

Code:
For x := 0 to bitmap.width - 1 do
  For y:= 0 to bitmap.height - 1 do
     case Bitmap.pixel[x,y] of
       White : WhitePoints.Add(x,y):
       Black : BlackPoints.Add(x,y):

Foreach Point W in WhitePoints do begin
  Foreach Point B in BlackPoints do
    W.Distances.Add(Distance(W,B));

  Output ('White Point ', W, 'Min=', W.Distance.Min, 'Max=', W.Distances.Max, 'Avg=',W.Distances.Avg);
end

Geändert von Furtbichler (13. Dez 2011 um 07:02 Uhr)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#4

AW: Abstand (min, max, avg) in Bitmap

  Alt 13. Dez 2011, 08:41
Sind das nun schwarze Punkte auf weissem Hintergrund, oder schwarze und weisse Punkte mite "Leerraum" dazwischen? Heisst "Punkt" bei dir Pixel, oder sind das eher kleine Pixelgrüppchen? Was ist der minimale und maximale Abstand in deinem Fall? (Verständnis des letzteren hängt von den anderen Fragen ab vermute ich.)

Eine Skizze, oder besser noch ein Realfall als Bild wären hier verdammt hilfreich. Weil so ohne weiteres an Kenntnis über die Struktur, bleibt erstmal wirklich nur alle paarweisen Abstände einzeln durchzukauen. Man kann zwar, wenn es nur um größer/kleiner geht zunächst die Wurzelei einsparen, aber es bleibt dennoch eine Zahlenschlacht
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
cltom

Registriert seit: 22. Sep 2005
221 Beiträge
 
Delphi 12 Athens
 
#5

AW: Abstand (min, max, avg) in Bitmap

  Alt 13. Dez 2011, 15:21
Vielen Dank einmal für die Antworten.

Zu den Fragen:

Die Bitmaps enthalten Kreise und Rechtecke in regelmäßiger Verteilung/Anordnung. Typischerweise 10-40% der Fläche ist schwarz. Im Wesentlichen ein (Loch)Gitter, Beispiel anbei.

Bekannt sind die Koordinaten der Punkte sowie deren Radius. Gesucht ist eben von jedem (weissen) Punkt der kleinstmögliche Weg zum nächsten schwarzen Punkt. Wenn ich also irgendwo auf einem weissen Pixel lande, wie weit ist der Weg maximal, bis ich zum nächsten schwarzen Punkt komme. Und über diesen Weg eine Art Histogramm oder eben min. max. avg. (der kürzeste Weg ist offensichtlich gerade ein Pixel zum nächsten Punkt, interessant sind mehr der mittlere und der längste Weg).

In Anlehnung an Deinen Vorschlag, Furtbichler, könnte man also die Randpunkte der Kreise nehmen und damit schon mal eingrenzen. Die Menge aller Punkte innerhalb des Kreises fällt weg, das reduziert den Aufwand.

Alternativ: ich gehe für jeden weissen Punkt alle (bekannten) Objekte durch und schaue, wie weit sie entfernt sind.

Je mehr ich darüber nachdenke, desto eher wird klar, dass der Ansatz falsch ist, es pixelbasiert zu lösen und nicht anhand der Koordinaten der Objekte ...
Miniaturansicht angehängter Grafiken
example.jpg  
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#6

AW: Abstand (min, max, avg) in Bitmap

  Alt 13. Dez 2011, 15:31
Darauf zielte meine Fragerei auch ab Wenn du die Mittelpunkte und Radien hast, wird das Problem ja fast schon trivial. Man kann sich zwar nicht sparen alle "weissen Pixel" durchzugehen, aber dann musst du ja nur noch die Abstände zu deinen Mittelpunkten minus der Radien errechnen.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#7

AW: Abstand (min, max, avg) in Bitmap

  Alt 13. Dez 2011, 20:23
Mal obiges in Code gegossen, da ich leider zuhause aber kein Delphi habe in C#. Aber das geht hoffe ich als Pseudocode durch (Achtung, grausig Quick&Dirty):
Code:
      public int[] CentersX, CentersY;
      public int[] Radii;
      
      public float MinDist(int x, int y)
      {
         float min = float.MaxValue;
         for (int i=0; i<CentersX.Length; i++)
         {
            float xx = x-CentersX[i];
            float yy = y-CentersY[i];
            float tmp = (float)(Math.Sqrt(xx*xx+yy*yy)-(float)Radii[i]);
            if (tmp<min) min = tmp;
         }
         return min;
      }
      
      void Button1Click(object sender, EventArgs e)
      {
         Bitmap b = new Bitmap(pictureBox1.Width, pictureBox1.Height);
         // Zufällige Kreise erzeugen. 4-9 Stück, mit Radius von 50-100 und Mittelpunkt im Bild
         Random rng = new Random();
         int count = (int)(rng.NextDouble()*5)+5; // im Bild unten war count = 9
         CentersX = new int[count];
         CentersY = new int[count];
         Radii = new int[count];
         for (int i=0; i<count; i++)
         {
            CentersX[i] = (int)(rng.NextDouble()*pictureBox1.Width);
            CentersY[i] = (int)(rng.NextDouble()*pictureBox1.Height);
            Radii[i] = (int)(rng.NextDouble()*50)+50;
         }
         for (int y=0; y<pictureBox1.Height; y++)
         {
            for (int x=0; x<pictureBox1.Width; x++)
            {
               float f = MinDist(x, y);
               // die Verwurstung mit 127 ist nur so, damit ich nachher nett auf Grauwerte zwischen 0 und 254 skalieren kann,
               // und die Abnahme in der Farbe doppelt so schnell ist wie die eigentliche Distanz. War optisch netter.
               if ((f>0) && (f<=127))
               {
                  int c = (int)((127-f)*2f);
                  b.SetPixel(x, y, Color.FromArgb(255, c, c, c));
               }
               else
               {
                  b.SetPixel(x, y, Color.Black);
               }
            }
         }
         pictureBox1.Image = b;
      }
Das Bild im Anhang ist so entstanden. Zumindest bei konstanten Radien ist man da, wie ich vermutet hatte, ganz ganz nah an der Delaunay-Triangulation. Vielleicht ist über diesen Weg noch etwas für dich herauszuholen, weil auch wenn man mit o.g. Variante "nur" O(Width*Height*CircleCount) hat, ist es zumindest für Echtzeiteinsätze kaum geeignet. (Der Code von mir unter C# brauchte für 800x600 Pixel große Bilder so runde 200-300ms auf einem Core i7 950.)
Edit: Schaut ein wenig aus wie ein Kalottenmodell


Eine ganz andere Idee wäre noch Gaussfilterung des Ausgangsbildes. Bei geeignet großem Radius des Filters sollte sich nachher ein zumindest ähnliches Bild ergeben, nur ist ein so großer, akkurater Gaussfilter auch nicht gerade der Performance bester Freund, und man würde da keine echten Distanzen bekommen, sondern nur ablesen können, an welchen Stellen sich die "Ridges" in den Mitten zwischen den Kreisen befänden. Am Ende muss man schließlich egal wie jeden Pixel einzeln anfassen.
Noch eine Methode wäre eine "missbrauchte" Shepard Interpolation, die aber das gleiche Laufzeitverhalten wie die oben implementierte Version hat.
Miniaturansicht angehängter Grafiken
kreise.png  
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium (13. Dez 2011 um 20:32 Uhr)
  Mit Zitat antworten Zitat
cltom

Registriert seit: 22. Sep 2005
221 Beiträge
 
Delphi 12 Athens
 
#8

AW: Abstand (min, max, avg) in Bitmap

  Alt 14. Dez 2011, 09:39
whow, das ist immer wieder unglaublich, wie schnell man hier hochwertiges Futter bekommt. Ich schaue mir das mal durch, vielen Dank!
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz