AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Leere Seite (blank page) filtern bei DelphiTwain

Leere Seite (blank page) filtern bei DelphiTwain

Ein Thema von Schwedenbitter · begonnen am 24. Aug 2015 · letzter Beitrag vom 26. Aug 2015
Antwort Antwort
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

AW: Leere Seite (blank page) filtern bei DelphiTwain

  Alt 25. Aug 2015, 17:40
Danke für Eure Antworten!
... Soweit ich mich erinnere, kann man aber auch ein Bild von Grau in Schwarz-Weiß umwandeln, indem man die Helligkeitsstufe festlegt, ab welcher das jeweilige Pixel weiß sein soll. Da würde ich mal ansetzen.
Dieser letzte Satz hat mich auf die - aus meiner Sicht - richtige Fährte geschickt. Für mich habe ich das Problem gelöst.

Zunächst habe ich das Bild nach schwarz/weiß umgewandelt. Mein nächster Ansatz war es dann, die schwarzen Pixel zu zählen. Anschließend habe ich diese mit den weißen ins Verhältnis gesetzt und ab einem Wert von 3 ‰ (Promille) das Bild als Bild mit Inhalt deklariert. Allerdings war das sehr fehlerbehaftet. Denn es gibt nicht nur Staub, Falten etc., sondern dann auch schwarze Ränder und - überholter Beitrag - schwarze Löscher.
Also schneide ich jetzt die Ränder innerhalb bestimmter Grenzen ab. Anschließend zähle ich die Anzahl der schwarzen Pixel. Wenn diese einen absoluten Wert überschreiten, ist es kein leeres Bild mehr. Das beschleunigt sogar die Suche, weil ich dann die Procedure verlassen kann.

Hier mein Code fürs Protokoll:
Delphi-Quellcode:
// Leeres Bild erkennen --------------------------------------------------------
// MaxBlack ist die Anzahl maximal zulässiger schwarzer Pixel.
// Beim Scannen können schwarze Ränder, Staubkörner etc. auftreten. Um ein
// möglichst genaues Ergebnis zu erzielen werden zuerst die Ränder abge-
// schnitten und dann die Anzahl der dunkeln/schwarzen Pixel ermittelt.
// Der Wert selbst dürfte hardwareabhängig sein und kann deshalb als Variable
// übergeben werden.
Function TScanForm.PictureIsEmpty(Const BitMap: TBitmap;
   Const MaxBlack: Integer = 75): Boolean;
Const
   lMargin         = 12;                              // linker Rand
   rMargin         = 8;                              // rechter Rand
   bMargin         = 4;                              // unterer Rand
   tMargin         = 8;                              // oberer Rand
   Tolerance      = 118;                           // guter Schwarz-Wert
Var
   lWidth         : Integer;
   lHeight         : Integer;
   lBlack         : Int64;
   I, J            : Integer;
   lLine            :^TRGBTriple;
Begin
   Result:=True;                                    // ausgehen von leerem Bild
   lWidth:= BitMap.Width - lMargin - rMargin;      // maximale Breite
   lHeight:=BitMap.Height - tMargin - bMargin;      // maximale Höhe
   BitBlt(Bitmap.Canvas.Handle, 0, 0, lWidth, lHeight,
      Bitmap.Canvas.Handle, lMargin, tMargin, SRCCOPY);
   BitMap.Width :=lWidth;
   BitMap.Height:=lHeight;
   If (Bitmap.PixelFormat <> pf24bit) Then
       Bitmap.PixelFormat := pf24bit;               // wegen Scanline
   lBlack:=0;                                       // schwarze Pixel

   For I:=0 To Pred(Bitmap.Height) Do               // alle Zeilen durchgehen
   Begin
      lLine:=Bitmap.Scanline[I];                     // Zeile zuweisen
      For J:=0 To Pred(Bitmap.Width) Do            // Zeile abarbeiten
      Begin
         If (lLine^.rgbtred + lLine^.rgbtBlue +
               lLine^.rgbtgreen) Div 3 < Tolerance Then
            Inc(lBlack);                           // = dunkler Wert -> schwarz
         If (lBlack >= MaxBlack) Then               // viele schwarze Pixel
         Begin
            Result:=False;                           // = Bild mit Inhalt
//         Exit;                                    // Zeit sparen!!!
         End;
         Inc(lLine);                                 // nächste Zeile durchsuchen
      End;
   End;

// TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TE
   fList.Append(IntToStr(fCount) + ';' + IntToStr(BitMap.Height * BitMap.Width) +
      ';' + IntToStr(lBlack));
// TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TE
End;
Alex Winzer
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
673 Beiträge
 
#2

AW: Leere Seite (blank page) filtern bei DelphiTwain

  Alt 25. Aug 2015, 23:27
Delphi-Quellcode:
         
If (lLine^.rgbtred + lLine^.rgbtBlue + lLine^.rgbtgreen) Div 3 < Tolerance Then
begin
  Inc(lBlack); // = dunkler Wert -> schwarz
  If (lBlack >= MaxBlack) Then // viele schwarze Pixel
  Begin
    Result:=False; // = Bild mit Inhalt
// Exit; // Zeit sparen!!!
  End;
End;
Noch schneller...
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#3

AW: Leere Seite (blank page) filtern bei DelphiTwain

  Alt 26. Aug 2015, 00:08
Zunächst habe ich das Bild nach schwarz/weiß umgewandelt. Mein nächster Ansatz war es dann, die schwarzen Pixel zu zählen. Anschließend habe ich diese mit den weißen ins Verhältnis gesetzt und ab einem Wert von 3 ‰ (Promille) das Bild als Bild mit Inhalt deklariert. Allerdings war das sehr fehlerbehaftet. Denn es gibt nicht nur Staub, Falten etc., sondern dann auch schwarze Ränder und - überholter Beitrag - schwarze Löscher. Also schneide ich jetzt die Ränder innerhalb bestimmter Grenzen ab. Anschließend zähle ich die Anzahl der schwarzen Pixel. Wenn diese einen absoluten Wert überschreiten, ist es kein leeres Bild mehr. Das beschleunigt sogar die Suche, weil ich dann die Procedure verlassen kann.
Diese beiden Werte – 3 Promille und deinen absoluten Wert an schwarzen Pixeln – kannst du, wenn du es komfortabler gestalten möchtest, dem Anwender als einstellbar überlassen, da ja nicht alle Scanner gleich gut oder schlecht scannen und die Verkratzungs- und/oder Verschmutzungsrate des Scanglases auch unterschiedlich sein kann. So könnte der Anwender dann Dokumente mit wenig sehr kleiner Schrift, die sonst vielleicht als leer gekennzeichnet würden, ebenfalls einstellen. Noch komfortabler wäre dann das Abspeichern diverser benutzerdefinierter Konfigurationen.

Bei dem Ganzen sehe ich aber noch ein Problem: Es kann durchaus vorkommen, daß auf einem Din-A-4-Blatt nur ganz ganz wenig Text steht oder nur ein klitzekleines Logo eingescannt werden soll. In diesem Fall könnte es sein, daß ein daraus resultierendes Bitmap ebenfalls als leer interpretiert würde. Daher sollte man vielleicht noch überprüfen, ob soundsoviele Pixel nebeneinander schwarz sind und bei einer – wiederum durch den Anwender einstellbaren – Größe das Bild durchgehen lassen. Sicher kennst du dieses Prinzip aus Tracing-Programmen, die Pixelbilder in Vektorgrafiken umwandeln wie z.B. Corel Trace.
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#4

AW: Leere Seite (blank page) filtern bei DelphiTwain

  Alt 26. Aug 2015, 07:24
Danke für die weiteren Anmerkungen!

@Jens01
Ich bin natürlich immer an noch schnellerem Code interessiert; auch weil Büro-PC in der Regel keine Höllenmaschinen sind und die Bildbearbeitung die Dinger nicht aufhalten sollte.
Ich muss aber gestehen, dass ich die Beschleunigung am Code selbst nicht auf den ersten Blick erkennen kann. Ich interpretiere das so, dass die Abfrage immer nur dann durchgeführt wird, wenn er einen schwarzen Pixel findet und sonst nicht. Wenn das Bild aber weiß ist, "scannt" er sowieso das gesamte Bild. Und wenn er schwarz ist, fliegt er spätestens einen Zyklus später raus? Kann man die Beschleunigung messen?

@Perlsau
Das habe ich schon gebastelt. Meine Leute haben jetzt die Möglichkeit, über das Menü genau diese Werte zu manipulieren. Ich habe etliche Tests gemacht. Im Rahmen dessen habe ich festgestellt, dass ich immer von Farbbildern ausgegangen bin. Bei Grau- oder Schwarzweiß-Bildern passen diese Wert nur sehr bedingt. Ich habe daher mal ein Screenshot angehängt, was aus meiner sich sinnvolle Einstellungen sind.
Ich habe bei meinen Tests auch mit den extremen gespielt . Ich habe also "leere" Seiten mit eingeschmuggelt, auf denen mit immer dünner werdenden Bleistiftstrichen Smileys gemalt sind, die man kaum mit dem bloßen Auge erkennen kann. Diese wurden gefunden und als "nicht leer" identifiziert. Es kann aber wirklich am guten Seitenscanner liegen - obwohl dieser nach 5 Jahren auch schon einen Rotstich hat...

Aber dass ich so schnell zum Ziel gekommen bin, hatte ich auch selten. Danke für Eure qualifizierte Hilfe!
Angehängte Grafiken
Dateityp: png Screenshot_0001.png (16,4 KB, 20x aufgerufen)
Angehängte Dateien
Dateityp: pdf Scantests.pdf (20,6 KB, 7x aufgerufen)
Alex Winzer
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#5

AW: Leere Seite (blank page) filtern bei DelphiTwain

  Alt 26. Aug 2015, 09:47
Aber dass ich so schnell zum Ziel gekommen bin, hatte ich auch selten. Danke für Eure qualifizierte Hilfe!
Genau dafür ist dieses Forum da, denke ich: Sich gegenseitig behilflich zu sein und damit Zeit, Arbeitsaufwand, Sackgassen und Fehler zu sparen. Freut mich, daß ich helfen konnte
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
673 Beiträge
 
#6

AW: Leere Seite (blank page) filtern bei DelphiTwain

  Alt 26. Aug 2015, 11:52
Zitat:
Ich interpretiere das so, dass die Abfrage immer nur dann durchgeführt wird, wenn er einen schwarzen Pixel findet und sonst nicht. Wenn das Bild aber weiß ist, "scannt" er sowieso das gesamte Bild. Und wenn er schwarz ist, fliegt er spätestens einen Zyklus später raus? Kann man die Beschleunigung messen?
Du zählst dies lBlack hoch und prüfst es gegen eine Konstante. Du brauchst es aber nur prüfen, wenn es sich verändert hat (Inc(lBlack)). Ansonsten ist das Ergebnis der Prüfung (if lBlack >= MaxBlack then) gleich mit dem des vorherigen Schleifendurchlauf.
Wenn die Hauptschleifen oft durchlaufen wird, kann sich des schon zeitlich auswirken.
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#7

AW: Leere Seite (blank page) filtern bei DelphiTwain

  Alt 26. Aug 2015, 12:15
...
Wenn die Hauptschleifen oft durchlaufen wird, kann sich des schon zeitlich auswirken.
OK. Das überzeugt mich. Ich habe es geändert.

Wenn ich Zeit und Lust habe, kann ich ja mal testen, wie es sich auswirkt. Vermutlich muss ich dazu aber ein festes Bitmap nutzen. Denn selbst beim selben Rohmaterial (=Papierseiten) kommen jedes Mal andere Bilder über den Scanner.
Alex Winzer
  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: Leere Seite (blank page) filtern bei DelphiTwain

  Alt 26. Aug 2015, 12:23
So als Verbesserungsvorschlag:

Verkleinere die Bitmaps, die du durchsuchen willst z.B. auf 300x300 Pixel. Durch das Zusammengematsche fallen einzeln stehende Punkte (Staub, kleine Kratzer) schon dabei raus und die Stellen mit Text tauchen als schwarze Balken auf. (jetzt mal Schwarz-Weiß betrachtet)
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
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 16:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz