AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Zusammenhängene Pixel zählen
Thema durchsuchen
Ansicht
Themen-Optionen

Zusammenhängene Pixel zählen

Ein Thema von Eichhoernchen · begonnen am 2. Jul 2006 · letzter Beitrag vom 5. Jul 2006
Antwort Antwort
Seite 1 von 2  1 2      
Eichhoernchen

Registriert seit: 22. Apr 2004
Ort: Hagen
322 Beiträge
 
Turbo Delphi für Win32
 
#1

Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 00:25
Hi, ich hatte vor eine function zu schreiben, die aus einem schwarz/weiß Bild alle Stücke heraus löscht, bei denen die Anzahl der zusammenhängenden schwarzen Pixel kleiner als 100 ist.

Ich hab mir dass folgender maßen gedacht, ein array of array of TPoint;
Die 1. Array dimension gibt den Pixelbrocken an, und in die 2. Dimension werden dann alle TPoint Werte des Pixelbrockens gespeichert.

Ich habe mir jetzt folgenden Code zusammengedacht aber leider klappt es nicht jedoch weiß ich auch nicht wo ich einen Fehler gemacht hab, also bitte helft mir(ich glaube bei der Verwendung von setlength, bin aber nicht sicher)

Delphi-Quellcode:
function killsmallareas(bmp : TBitmap) : TBitmap;
var i, j, k, l : integer;
    Polygones : array of array of TPoint;
    found : boolean;
Begin
result := TBitmap.Create;
result.Width := bmp.Width;
result.Height := bmp.Height;
result.PixelFormat := bmp.PixelFormat;
SetLength(polygones, 1, 1);
 for i := 0 to bmp.Width - 1 do
  for j := 0 to bmp.Height - 1 do
   Begin
    if bmp.Canvas.Pixels[i, j] = clblack
      then Begin
            with bmp.Canvas do
             Begin
               if (Pixels[i-1, j] = clblack) or (Pixels[i-1, j-1] = clblack)
               or (Pixels[i, j-1] = clblack) or (Pixels[i+1, j-1] = clblack)
               or (Pixels[i+1, j] = clblack) or (Pixels[i+1, j+1] = clblack)
               or (Pixels[i, j+1] = clblack) or (Pixels[i-1, j+1] = clblack)
                 then Begin
                       k := 0;
                       found := false;
                       while ( k < high(polygones)) and (found = false) do
                        Begin
                         l := 0;
                         while ( l < high(polygones[k])) and ( not(PointsEqual(polygones[k, l], Point(i-1, j)))
                          or not(PointsEqual(polygones[k, l], Point(i-1, j-1))) or not(PointsEqual(polygones[k, l], Point(i, j-1)))
                          or not(PointsEqual(polygones[k, l], Point(i+1, j-1))) or not(PointsEqual(polygones[k, l], Point(i+1, j)))
                          or not(PointsEqual(polygones[k, l], Point(i+1, j+1))) or not(PointsEqual(polygones[k, l], Point(i, j+1)))
                          or not(PointsEqual(polygones[k, l], Point(i-1, j+1))) ) do inc(l);
                         if l < high(polygones[k]) then found := true;
                         inc(k);
                        end;
                        if found
                          then Begin
                                dec(k);
                                SetLength(polygones[k], high(polygones[k])+1);
                                polygones[k, high(polygones[k])] := Point(i, j);
                               end
                          else Begin
                                setlength(polygones, high(polygones)+1);
                                setlength(polygones[high(polygones)], 1);
                                polygones[high(polygones), 0] := Point(i, j);
                               end;
                      end;
             end;
           end;
   end;
   for k := 0 to High(polygones) do
     if high(polygones[k]) > 100
       then for l := 0 to high(polygones[k]) do
             result.Canvas.Pixels[polygones[k, l].X, polygones[k, l].Y] := clblack;
end;

Ich hoffe man steigt durch den Code durch.


Vielen Dank schonmal für eure Antworten!
Jan
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#2

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 09:14
Guten Morgen, Jan.

Willst du deinen Code neu geschrieben bekommen oder sollen nur Fehler behoben werden? Du hast leider nicht geschrieben, was nicht funktioniert.

Noch ein paar allgemeine Hinweise in ungeordneter Folge und ohne Anspruch auf Vollständigkeit:

Die Matrix polygones würde ich mit (0,0) vordimensionieren, nicht mit (1,1).
Eine horizontale Linie mit weniger als 101 Pixeln Breite wird bei deinem Ansatz eliminiert - vielleicht solltest du deine Definition von "zusammenhängend" nochmal überdenken.
Der Zugriff über Pixels[] wird bei großen Bildern zu langsam (ScanLine).
Dein Pixel-Test scheitert an den Bildrändern.
Die Pixel-Tests sind redundant, statt acht Tests sind wahrscheinlich nur drei nötig.
(not found) ist besser als (found = False).
Der riesige boolsche Ausdruck mit PointsEqual() kann vereinfacht werden - (not a or not b) ist das gleiche wie not (a and b) - aber ob die Bedingung überhaupt richtig formuliert ist?
Am Ende übermalst du schwarze Pixel nochmal mit schwarz - was soll sich dabei ändern?

Grüße vom marabu
  Mit Zitat antworten Zitat
Eichhoernchen

Registriert seit: 22. Apr 2004
Ort: Hagen
322 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 09:33
Ne ich will natürlich nicht, dass ihr mir den Code neu schreibt, dass was du gemacht hast ist genau dass was ich wollte, habe da irgendwie nen Knoten im Kopf.

So, ja über die Initialisierung mit setlength war ich mir nicht klar, wenn ich mit (0,0) initialisiert habe, hat high() immer -1 als Ergebnis gebracht. Über high sagt die Delphi hilfe dass es -1 als Ergebnis zurück gibt wenn das array leer ist, heißt leer im Sinne von ohne Werte oder unterdimensioniert?

Wie kann ich dass mit scanline umsetzen? damit kann ich doch immer nur 1 Pixel betrachten und nicht mehrere oder?

Zitat:
Eine horizontale Linie mit weniger als 101 Pixeln Breite wird bei deinem Ansatz eliminiert
ne ist schon richtig das eine Linie mit weniger als 100 Pixeln elemeniert werden soll.


Ich hatte zuerst auch weniger Abfragen für die Pixel, und zwar immer nur links, rechts, oben, obenlinks und obenrechts, jedoch würde das Pixel dann aus der Liste fallen wenn in diesen bereich kein schwarzes Pixel aber unten drunter eins. Und ich glaube es war nicht schlimm ob man über den Rand hinaus ging!



Zitat:
(not a or not b) ist das gleiche wie not (a and b)
Das werd ich überarbeiten, das würde es schonmal übersichtlicher machen, aber er tut ja das Selbe, also ist es ja nicht falsch.

Zitat:
Am Ende übermalst du schwarze Pixel nochmal mit schwarz - was soll sich dabei ändern?
Nein ich Zeichne alle Bereiche mit mehr als 100 Pixeln auf eine neue Bitmap, die der Rückgabewert ist.


Ist der Ansatz überhaupt gut, dass mit einem array zu machen, wie wäret ihr denn an das Problem heran gegangen?
Jan
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#4

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 10:21
Hallo!

Zitat von Eichhoernchen:
ich glaube bei der Verwendung von setlength, bin aber nicht sicher
Meinst du vielleicht diese Stellen (Zeilen 43 und 47)?

SetLength(polygones[k], high(polygones[k])+1); High(Array) liefert den Index des obersten Elements, High(Array) + 1 also die aktuelle Länge des Arrays...

Gruß Hawkeye
  Mit Zitat antworten Zitat
Eichhoernchen

Registriert seit: 22. Apr 2004
Ort: Hagen
322 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 10:38
Zitat von Hawkeye219:
High(Array) liefert den Index des obersten Elements, High(Array) + 1 also die aktuelle Länge des Arrays...

Gruß Hawkeye

das heißt damit ich das Array um eins verlänger, muss ich:
SetLength(polygones[k], high(polygones[k])+2); Dann werd ich dass mal Testen!
Jan
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#6

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 11:26
Das sieht schon besser aus. Dummerweise habe ich dir eine Information vorenthalten: die Standardfunktion Length kann man auch auf dynamische Arrays anwenden, sie liefert dann die Länge des Arrays:

Length(ArrayVar) = High(ArrayVar) + 1 Damit kannst du deine letzte Anweisung noch etwas lesbarer gestalten:

SetLength (polygones[k], Length(polygones[k]) + 1); Jetzt sieht man mit einem Blick, daß hier ein Array um ein Element vergrößert wird.

Gruß Hawkeye
  Mit Zitat antworten Zitat
Eichhoernchen

Registriert seit: 22. Apr 2004
Ort: Hagen
322 Beiträge
 
Turbo Delphi für Win32
 
#7

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 11:33
ahh wunderbar, ich dachte immer high wäre das length von dynamischen arrays.


So geändert hab ich das, leider klappt es immernoch nicht. ich hab nen bild erstellt mit nem großen Pixelblock, 225 Pixeln (15x15)
jedoch bekomm ich steht ein weißes Bild am Ende....
Jan
  Mit Zitat antworten Zitat
Benutzerbild von Nikolas
Nikolas

Registriert seit: 28. Jul 2003
1.528 Beiträge
 
Delphi 2005 Personal
 
#8

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 12:12
Delphi-Quellcode:
Procedure Next(var cnt: integer; x,y: integer; stop: integer);
begin
if stop then exit;

pixel[x,y].color:=clmaroon; // Gezähltes Pixel wird markiert

if Pixel[x+1,y+1]=clblack then // ein Nachbar wird überprüft
 begin
 inc(cnt);
 next(cnt,x+1,y+1, stop);
 end;

if Pixel[x,y+1]=clblack then
  ...
if ..
if ..

if cnt>100 then // Fertig.
 begin
 Myfloodfill(x,y);
 stop:= true; // alle anderen Ableger der Funktion sterben
 end;

end;

Procedure Myfloodfill(x,y); // sollte klar sein.
begin
pixel[x,y].color:= :=clnone;

if Pixel[x+1,y].color:=clmaroon then myfloodfill[x+1,y];
if ..
if ..
if ..
end;

Die Idee sollte klar sein. Du suchst nach einem schwarzen Pixel und rufst die Suchfunktion rekursiv für die schwarzen Nachbarn auf. Ein Gefundenes Feld wird Rot angemalt, damit es nicht nochmal gezählt wird, sonst verwickeln schon zwei benachbarte schwarze die Funktion in eine Endlosschleife. Jede neu erzeugte Suchfunktion meldet ihre Treffer an einen Zähler und sobald irgendwo das hunderste Feld gefunden wurde, wird die Suche abgebrochen und die Felder angemalt. Bei meiner Methode brauchst du dir nicht zu merken, welche Felder du durchlaufen hast, weil du den Weg einfach rekonstruieren kannst.

Bis auf Feinheiten, sollte das so funktionieren und wäre dann deutlich einfacher als dein Code. Obs schneller ist, weiss ich nicht, aber das sollte rauszufinden sein.
Erwarte das Beste und bereite dich auf das Schlimmste vor.
  Mit Zitat antworten Zitat
loetmann

Registriert seit: 22. Dez 2003
Ort: Rostock
33 Beiträge
 
Delphi 3 Standard
 
#9

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 13:04
Hallo,

Zitat von Eichhoernchen:
Wie kann ich dass mit scanline umsetzen? damit kann ich doch immer nur 1 Pixel betrachten und nicht mehrere oder?
Mit scanline greifst du auf eine komplette Zeile eines Bitmaps zu.

Folgendes setzt einen RGB Pixel in einem RGB Bild:

Delphi-Quellcode:
procedure mp_setpixel(x,y:integer;r,g,b:byte;bitm:TBitmap);
var p:PByteArray;
begin
 p:=bitm.ScanLine[y];
 p[x*3] :=b;
 p[x*3+1]:=g;
 p[x*3+2]:=r;
end;
Eine Zeile ist dann ein Array das bei RGB-Bilder so Aufgebaut ist: bgrbgrbgr...
(der Zugriff ist dann Schneller als Pixels)

Wenn Du z.B. 2 Zeilen gleichzeitig betrachten möchstest kannst Du mit
Delphi-Quellcode:
p:=bitm.ScanLine[4];
p1:=bitm.ScanLine[5];
auf die 4. und 5.Zeile zugreifen. (Zählung ab 0)

Ein Gruß
  Mit Zitat antworten Zitat
Eichhoernchen

Registriert seit: 22. Apr 2004
Ort: Hagen
322 Beiträge
 
Turbo Delphi für Win32
 
#10

Re: Zusammenhängene Pixel zählen

  Alt 2. Jul 2006, 22:51
Jo das war mir schon klar, nur bin ich nicht sicher ob da nicht der Aufwand, wenn ich 3 scanlines brauche größer ist als eben über pixels anzusprechen.

Naja gut das ist "tuning", wenn es klappt kann werde ich dass machen, aber rein von der Übersicht ist es mit pixels deutlicher.
Jan
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 17:48 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