AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Überflüssigen Hindergrund bei Bildern entfernen
Thema durchsuchen
Ansicht
Themen-Optionen

Überflüssigen Hindergrund bei Bildern entfernen

Ein Thema von MuTzE.Y85 · begonnen am 26. Jun 2013 · letzter Beitrag vom 10. Jul 2013
Antwort Antwort
Benutzerbild von MuTzE.Y85
MuTzE.Y85

Registriert seit: 11. Apr 2006
152 Beiträge
 
#1

Überflüssigen Hindergrund bei Bildern entfernen

  Alt 26. Jun 2013, 20:55
Hi,

ich arbeite zurzeit an einer Routine um überflüssigen Hintergrund eines Bildes zu entfernen.

Kurz erklärt:

Ich habe ein Foto von einem Gegenstand, auf einem weißen Hintergrund.
Der Hintergrund steht an jeder Seite etwas über. Ein normales Bild halt.
Jetzt möchte ich den weißen Hintergrund an jeder Seite soweit entfernen bis an jeder Seite die Außenkanten des Gegenstands an den Bildrand grenzen.

Verstanden?

Ein Beispielbild ist im Anhang. Das Bild soll quasi auf die Außenkannten eines Kreises verkleinert/beschnitten werden.



Mit Scanline klappt das oben und unten sehr gut.
Ich durchlaufe jede Zeile und prüfe, ob in der Zeile ein Pixel vorkommt, der nicht Weiß ist.
Finde ich einen, habe ich die Zeile wo der z.B. Kreis anfängt.

Jetzt ist nur die Frage: Wie mache ich das Vertikal? Also links und rechts.
Scanline macht ja da keinen Sinn oder?
Aber wenn ich das mit Pixels mache, dauerts doch zu lange oder?

Eine Möglichkeit wäre, das Bild um 90° zu drehen und das Ganze dann nochmal mit Scanline laufen zu lassen und wieder zurück zu drehen.


Fällt jemandem vielleicht eine bessere Lösung ein?
Miniaturansicht angehängter Grafiken
vorher.jpg   nachher.jpg  
LAN-PC: C2Q Q9550 @ 4004 MHz @ 1.232 V @ Mugen 2 | DFI LANParty JR P45-T2RS | G.Skill 4GB DDR2-1000 CL5 | ZOTAC GTX 280 @ GTX 285 @ 1.06 V | WD Caviar Blue 320GB / WD Caviar Black 640GB | BeQuiet DPP P7 450W | Antec Mini P180
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 26. Jun 2013, 21:35
Wenn das Objekt konvex ist, ist dein Ansatz doch eine ganz gute Lösung. Wenn es konkav ist, ist FloodFill wahrscheinlich das, was du suchst (entspricht dem Farbeimer bei Paint).

Edit: Achso, zu Scanline: Du kannst alle Scanline-Pointer in einem Array zwischenspeichern, dann geht das auch vertikal. Oder noch besser, du sorgst dafür, dass die Scanlines im Speicher alle direkt hintereinanderstehen, dann ist es mit einfacher Pointer-Arithmethik getan. Das ist beim normalen TBitmap leider nicht gegeben, da müsstest du entweder in einen extra Speicherbereich umkopieren oder du nimmst TBitmap32 von Graphics32, da wird das so gemacht (vermutlich einer der Hauptgründe, warum Graphics32 so schnell ist im Vergleich zum normalen Canvas/Bitmap).

Geändert von Namenloser (26. Jun 2013 um 21:38 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#3

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 26. Jun 2013, 22:49
So sollte es gehen:
Code:
var left, right, top, bottom: integer := 0;

für jede Zeile y := 0 .. height-1:
  für jede Spalte x := 0 .. width-1:
    wenn pixel[x,y] <> WEIß dann:
      top := min(top, y);
      bottom := max(bottom, y);
      left := min(left, x);
      right := max(right, x);
Das kannst du sicher so umsetzen, dass es Scanline benutzt

Man könnte einige min und max einsparen, aber so sollte das Grundprinzip klar werden:
Gesucht ist die x-Koordinaten der nicht-weißen Pixel am weitesten links und rechts sowie die y-Koordinaten der nicht-weißen Pixel am weitesten oben und unten.

Wenn die Ränder verhältnismäßig klein sind, könnte es etwas bringen, top und bottom beziehungsweise left und right aus unterschiedlichen Richtungen zu suchen.
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.

Geändert von BUG (26. Jun 2013 um 22:54 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.620 Beiträge
 
Delphi 12 Athens
 
#4

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 27. Jun 2013, 08:56
Das hatten wir schon einmal hier: http://www.delphipraxis.net/166570-groesse-timage.html
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 27. Jun 2013, 09:07
@bug

left und top werden bei deinem Ansatz aber immer 0 sein
Diese Werte müssen initial auf left := width und top := height gesetzt werden
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#6

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 27. Jun 2013, 09:11
Diese Werte müssen initial auf left := width und top := height gesetzt werden
Stimmt
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.
  Mit Zitat antworten Zitat
Benutzerbild von MuTzE.Y85
MuTzE.Y85

Registriert seit: 11. Apr 2006
152 Beiträge
 
#7

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 29. Jun 2013, 00:52
Also ob das Objekt konkav oder konvex ist spielt eigentlich keine Rolle. Es soll ja einfach nur der Anfang gefunden werden.

Also für Oben und Unten habe ich schon den Code.
Die Frage ich jetzt nur wie ich Links und Rechts prüfe.

Oben
Code:
for H := 0 to aBitmap.Height - 1 do
  begin
  // Zeile einlesen
  P := aBitmap.ScanLine[H];
     
  // Wenn Anfang noch nicht gefunden, dann prüfen
  if RowFound = False then
    begin

      for W := 0 to aBitmap.Width - 1 do
        begin
          // Wenn Pixel nicht weiß, dann Zeile merken
          if not (RowFound = True) and not (P^[1] = 255) and not (P^[2] = 255) and not (P^[3] = 255) then
            begin
              Row := H;
              RowFound := True;
            end;
          Inc(P);
        end;

    end;

  end;

Unten das Gleiche nur mit downto in der Schleife.

Prüfe ich jetzt links und rechts gleich in den schleifen oder wie mache ich das am Besten?
Momentan scheint mir die einfachste Lösung das Drehen des Bildes zu sein.
Wäre aber cool wenn es auch so gehen würde.
LAN-PC: C2Q Q9550 @ 4004 MHz @ 1.232 V @ Mugen 2 | DFI LANParty JR P45-T2RS | G.Skill 4GB DDR2-1000 CL5 | ZOTAC GTX 280 @ GTX 285 @ 1.06 V | WD Caviar Blue 320GB / WD Caviar Black 640GB | BeQuiet DPP P7 450W | Antec Mini P180

Geändert von MuTzE.Y85 (29. Jun 2013 um 00:56 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 29. Jun 2013, 00:56
Warum machst du das nicht so wie in #3 erläutert?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von MuTzE.Y85
MuTzE.Y85

Registriert seit: 11. Apr 2006
152 Beiträge
 
#9

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 29. Jun 2013, 01:15
Ich hatte das System nicht gleich verstanden.

Ich werde das bei Gelegenheit mal mit Scanline probieren.
Wenn es klappt poste ich hier gleich die Lösung.

Danke schon mal!
LAN-PC: C2Q Q9550 @ 4004 MHz @ 1.232 V @ Mugen 2 | DFI LANParty JR P45-T2RS | G.Skill 4GB DDR2-1000 CL5 | ZOTAC GTX 280 @ GTX 285 @ 1.06 V | WD Caviar Blue 320GB / WD Caviar Black 640GB | BeQuiet DPP P7 450W | Antec Mini P180
  Mit Zitat antworten Zitat
Benutzerbild von MuTzE.Y85
MuTzE.Y85

Registriert seit: 11. Apr 2006
152 Beiträge
 
#10

AW: Überflüssigen Hindergrund bei Bildern entfernen

  Alt 10. Jul 2013, 22:24
Für alle die das Gleiche suchen hier noch das Ganze mit Scanline:

Code:
uses
  Math;

procedure RemoveBackground(aBitmap: TBitmap);
type
  PixArray = Array [1..3] of Byte;
var
  P: ^PixArray;
  X,Y, aLeft, aBottom, aTop, aRight: Integer;
begin
  aBitmap.PixelFormat := pf24Bit;

  aTop := aBitmap.Height;
  aLeft := aBitmap.Width;
  aBottom := 0;
  aRight := 0;

  for Y := 0 to aBitmap.Height - 1 do
    begin
      P := aBitmap.ScanLine[Y];

      for X := 0 to aBitmap.Width - 1 do
        begin
          if not (P^[1] = 255) and not (P^[2] = 255) and not (P^[3] = 255) then
            begin
              aTop := Min(aTop, Y);
              aBottom := Max(aBottom, Y);
              aLeft := Min(aLeft, X);
              aRight := Max(aRight, X);
            end;
          Inc(P);
        end;
    end;

  aBitmap.Canvas.CopyRect(Rect(0, 0, aBitmap.Width - aLeft - (aBitmap.Width - aRight) + 1, aBitmap.Height - aTop - (aBitmap.Height - aBottom) + 1), aBitmap.Canvas, Rect(aLeft, aTop, aRight + 1, aBottom + 1));
  aBitmap.Height := aBitmap.Height - aTop - (aBitmap.Height - aBottom) + 1;
  aBitmap.Width := aBitmap.Width - aLeft - (aBitmap.Width - aRight) + 1;
end;
Danke nochmal speziell an BUG und Sir Rufo!
LAN-PC: C2Q Q9550 @ 4004 MHz @ 1.232 V @ Mugen 2 | DFI LANParty JR P45-T2RS | G.Skill 4GB DDR2-1000 CL5 | ZOTAC GTX 280 @ GTX 285 @ 1.06 V | WD Caviar Blue 320GB / WD Caviar Black 640GB | BeQuiet DPP P7 450W | Antec Mini P180
  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 12:41 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