Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Text bereinigen: kurze Wörter löschen (https://www.delphipraxis.net/192747-text-bereinigen-kurze-woerter-loeschen.html)

erich.wanker 16. Mai 2017 16:35

Text bereinigen: kurze Wörter löschen
 
Hallo,
eine Frage:

ich hab in einem Textfile einen Text (ziemlicher Buchstaben-Müll..)

Ich ignoriere die ganzen Sonderzeichen wie folgt:
(und schreibe den Text in ein Datenbankfeld..)

Code:
for i := 0 to text_aus_file.Count - 1  do
begin
s:=text_aus_file.Strings[i];

neu:='';
for x := 0 to Length(s)-1 do
begin
 if (s[x] in ['0'..'9','a'..'z', 'A'..'Z','ä','ö','ü','ß','Ä','Ö','Ü',' ']) then neu:=neu+s[x];
end;

TEXT.Edit;
TEXT.FieldByName('TEXT').AsString:=TEXT.FieldByName('TEXT').AsString+neu;
TEXT.Post;

end;
im Text kommen sehr viel Müll vor - Rohdaten von einem EXTREMEN Beispiel:
Zitat:

Sie wurde den Kontrahenten,
weiche handlungs- und verfügungfähig sind, zur Kenntnis
gebracht und von denselben in seiner Gegenwart unterzeichnet.
seht EGHiig
W]Hp de age
EZ
gegen
Ir
sr
die
k ß
Angaben
PP
\
& S S
v RSS
$ k eigen (si i tik N n ut sl Win uit n r un de kn Si e W St We t d W s gene an Site
Eingetragen: Band:
gel ee
3 g i : “ .
& Ü S s ® m Hosen e dere nn In en h Wenn ie n se sh ln on {w'a_$‘ +3 RE



Meine Frage:
Wie kann ich nun Wörter (mit und ohne Zahlen) mit 1, 2, und 3 Wort-Länge auch noch löschen ... so kurze Wörter haben keine Relevanz... mich interessieren nur die Wörter und Zahlen ab 4 Stellen Länge


Vielen Dank für Hinweise

LiGrü
Erich

nahpets 16. Mai 2017 17:04

AW: Text bereinigen: kurze Wörter löschen
 
Sowas?
Delphi-Quellcode:
var
  neu : String;
  s : String;
  bereinigt : String;
begin
  for i := 0 to text_aus_file.Count - 1 do begin
    s := text_aus_file.Strings[i];
    neu := '';
    bereinigt := '';
    for x := 1 to Length(s) do begin
      if (s[x] in ['0'..'9','a'..'z', 'A'..'Z','ä','ö','ü','ß','Ä','Ö','Ü',' ']) then begin
        neu := neu + s[x];
      end;
    end;
    if length(neu) > 5 then begin
      bereinigt := bereinigt + neu;
    end;
  end;
  TEXT.Edit;
  TEXT.FieldByName('TEXT').AsString := bereinigt;
  TEXT.Post;
end;

erich.wanker 16. Mai 2017 17:23

AW: Text bereinigen: kurze Wörter löschen
 
Hallo nahpets,

leider nicht ...

Als Beispiel
Ein String: " a uui ll ooorer Automobil j re 34a Flugzeug kf Schiffssegel"
sollte ergeben: "Automobil Flugzeug Schiffssegel"

- also alle "kurzen Wörter" aus einem String filtern...

nahpets 16. Mai 2017 17:29

AW: Text bereinigen: kurze Wörter löschen
 
so?
Delphi-Quellcode:
var
  neu : String;
  s : String;
  bereinigt : String;
begin
  for i := 0 to text_aus_file.Count - 1 do begin
    s := text_aus_file.Strings[i];
    neu := '';
    bereinigt := '';
    for x := 1 to Length(s) do begin
      case s[x] of
        '0'..'9',
        'a'..'z',
        'A'..'Z',
        'ä','ö','ü','ß','Ä','Ö','Ü' : neu := neu + s[x];
      else
        if length(neu) > 6 then begin
          bereinigt := bereinigt + neu + ' ';
          neu := '';
        end;
      end;
    end;
    TEXT.Edit;
    TEXT.FieldByName('TEXT').AsString := bereinigt;
    TEXT.Post;
  end;
end;

SneakyBagels 16. Mai 2017 17:55

AW: Text bereinigen: kurze Wörter löschen
 
Zitat:

Ein String: " a uui ll ooorer Automobil j re 34a Flugzeug kf Schiffssegel"
sollte ergeben: "Automobil Flugzeug Schiffssegel"
Zitat:

mich interessieren nur die Wörter und Zahlen ab 4 Stellen Länge
Dann hast du aber ein Problem. Denn ooorer hat 6 Zeichen und alles ab 4 interessiert dich doch.

Da musst du wohl mit einem Wörterbuch drüberfahren und Müll aussortieren.

HolgerX 16. Mai 2017 18:06

AW: Text bereinigen: kurze Wörter löschen
 
Hmm..

die Roh-Daten, welche Du uns gezeigt hast, ist das nen CopyPaste aus z.B. dem Windows-Editor?

Oder sind zwischen den Zeichen eventuell weitere (Steuer-) Zeichen, welche nur als Leerzeichen dargestellt werden?

Nur mal so ne Frage.. ;)

Oder kannst Du eine Original-Datei mal komplett anhängen?

p80286 16. Mai 2017 23:17

AW: Text bereinigen: kurze Wörter löschen
 
Das sieht aus wie die OCR vor 20 Jahren. Kannst Du uns die Quelle nennen?
Ich würde für das Wörterbuch plädieren.

Gruß
K-H

SneakyBagels 16. Mai 2017 23:20

AW: Text bereinigen: kurze Wörter löschen
 
Zitat:

Ich würde für das Wörterbuch plädieren.
Genau. Denn ohne wird es ihm wahrscheinlich nicht möglich sein zwischen Müll und Nicht-Müll zu unterscheiden.
Siehe " a uui ll ooorer Automobil j re 34a Flugzeug kf Schiffssegel"
Mindestlänge von 4 erfüllt, aber Müll.

erich.wanker 17. Mai 2017 09:13

AW: Text bereinigen: kurze Wörter löschen
 
Hallo Leute - vielen Dank für die Hinweise :-)

@p80286

Rohdaten sind aus "Tesseract OCR"

- ich verwende ghostscript, um PDF´s (bestehend meist aus gescannte A4 Seiten) in TIFF umzuwandeln...
- und ich verwende tesseract OCR, um TIFF´s in TXT umzuwandeln
- dann lade ich mir die TXT rein ... lösche "Füllwörter" (und, wie mit bei zu..) - da habe ich eine freie Liste online gefunen
und dann speichere ich mir den Rest in eine DB

@HolgerX

JA - die Rohdaten haben weitere Steuerzeichen (Returns und Co) - die ich durch Copy/past (als auch händisch) nicht im Posting habe


@SneakyBagels.
"..Problem "ooorer" hat 6 Zeichen und alles ab 4 interessiert dich doch"

Ja ... Ein Wörterbuch drüberlaufen lassen wäre natürlich perfekt - aber das überschreitet meine Fähigkeiten ;-)
Wie soll ich z.b: Aus "Autm0bll" ein "Automobil" machen ...

Und: Es sind viele Familiennamen und Regions-namen in den Texten - die findet man nicht in einer Wörterbuchliste - und die sind eigentlich meine wichtigsten Indikatoren

p80286 17. Mai 2017 10:44

AW: Text bereinigen: kurze Wörter löschen
 
Dann such mal nach "Kölner Phonetik / Levensthein / Soundex" da solltest Du hier recht schnell fündig werden.

Gruß
K-H
Edith:
http://phonetik.phil-fak.uni-koeln.d...artin_Wilz.pdf

Edith2:
Zitat:

Zitat von erich.wanker (Beitrag 1371724)
Und: Es sind viele Familiennamen und Regions-namen in den Texten - die findet man nicht in einer Wörterbuchliste - und die sind eigentlich meine wichtigsten Indikatoren

Wir hier werden doch wohl eine Liste mit Familiennamen erstellen können?
Und was verstehst Du unter "Regionen" ?

Blup 17. Mai 2017 14:55

AW: Text bereinigen: kurze Wörter löschen
 
Keine Wörterbuchliste sondern eine Wörterliste.
Also im einfachsren Fall eine Stringliste mit Wörtern.
Eventuell aber auch zwei Listen, eine Black- und eine White-Liste.
Die lädst du bei Programmstart aus Textdateien und speicherst diese wieder bei Programmende.
Beim Parsen schlägst du jedes Wort in deinem Text erst in der White-Liste nach, wenn dort vorhanden, bleibt es im Text.
Dann in der Blackliste, wenn dort vorhanden, fliegt es raus.
Ansonsten fragst du den Anwender, nach seiner Entscheidung fügst du das Wort in eine der Listen ein.

hanvas 17. Mai 2017 15:26

AW: Text bereinigen: kurze Wörter löschen
 
Zitat:

Zitat von erich.wanker (Beitrag 1371724)

Rohdaten sind aus "Tesseract OCR"

- ich verwende ghostscript, um PDF´s (bestehend meist aus gescannte A4 Seiten) in TIFF umzuwandeln...
- und ich verwende tesseract OCR, um TIFF´s in TXT umzuwandeln
- dann lade ich mir die TXT rein ... lösche "Füllwörter"

Tesseract kann das eigentlich deutlich besser. Wie verwendest Du Tesseract denn, über die Kommandozeile oder als DLL mit der CAPI?

Bei Interesse kann ich eine Portierung der C API hier hochladen damit man Tesseract als DLL einbinden kann.

Unabhängig davon, schau die mal [1][2] und [3] an. Die Methoden funktionieren mit der API Version ebenso wie mit der Komandozeile.

Zitat:

Zitat von erich.wanker (Beitrag 1371724)
Ja ... Ein Wörterbuch drüberlaufen lassen wäre natürlich perfekt - aber das überschreitet meine Fähigkeiten ;-)

Das hat Tesseract schon eingebaut. Du kannst sowohl mit der Komandozeile wie auch der CAPI Version eigene Wörterbücher mitgeben. Das ist eine der Maßnahmen um das Erkennungsergebnis an sich deutlich zu verbessern. Aber Achtung ! Ein Wörterbuch auf Tesseract Ebene schränkt die Erkennungsergebnisse weitgehend ein. Das wirkt wie eine Whitelist.

Zitat:

Zitat von erich.wanker (Beitrag 1371724)
Wie soll ich z.b: Aus "Autm0bll" ein "Automobil" machen ...

Indem Du eine Liste der erlaubten Wörter aufstellst, ein Maß für die Abweichung zwischen zwei Wörtern definierst. (Beispielsweise 0-1 wobei 0 keine Übereinstimmung und 1 eine max. Übereinstimmung bedeutet). Dein gefundenes Wort mit dieser Liste vergleichst, und das Paar mit der kleinsten Abweichung ermittelst. Ist die Abweichung in einem Rahmen den Du noch erlaubst nimmst du den gefundenen wert her, ist die Abweichung zu groß dann hast Du Müll.

Die üblichen "Ähnlichkeitsmaße" sind bei OCR Daten übrigens meistens nicht so toll, da es sich nicht um Tippfehler (wie bei Levenstein) oder phoenetisch gleiche Begriffe (wie bei Müller und Mueller) sondern um visuelle Ähnlichkeiten handelt. Unter den Standard-Algorithmen ist der Jaro Winkler / Dice noch am besten geeignet, oder Du arbeitest mit Homoglyph Tabellen. Eine kleine Hilfe ist vielleicht das Nachfolgende (den größten Teil aus [4] entnommen)

[SOURCE]

uses
SysUtils, Math;

type
TBigram = string[2];
TBigrams = array of TBigram;


function TokenizeString(Str: String; IgnoreCase: Boolean): TBigrams;
var
i : Integer;
l : Integer;
begin
i:=0;
l:=Length(Str);

if IgnoreCase then
Str:=AnsiUpperCase(Str);

SetLength(Result, Ceil(l/2));

if l=0 then
Exit;

while i<=High(Result) do
begin
Result[i]:=TBigram(copy(Str, (2*i)+1, 2));
inc(i);
end;
end;

function StringSimilarityRatio(const Str1, Str2: String; IgnoreCase: Boolean): Double;
var
commonTerms: Integer;
Bigrams1,
Bigrams2 : TBigrams;
idx : Integer;
begin
commonTerms:=0;
Bigrams1:=TokenizeString(Str1, IgnoreCase);
Bigrams2:=TokenizeString(Str2, IgnoreCase);

for idx := 0 to Min(High(Bigrams1), High(Bigrams2)) do
begin
if Bigrams1[idx]=Bigrams2[idx] then
Inc(commonTerms);
end;

Result:=2 * commonTerms / (Length(Bigrams1) + Length(Bigrams2));
end;

// Beispiel wie du das einbauen kannst.

function CheckDict (const searchFor : String; Dictionary : TStrings; var s : String ) : Double;
var i : Integer;
r : String;
d : Double;
begin
result := 0.0;
s := '';
for i := 0 to Dictionary.Count-1 do
begin
d := StringSimilarityRatio(dictionary[i],searchFor);
if d>result then
begin
s := dictionary[i];
result := d;
end;
end;
end;

[/SOURCE]

Zitat:

Zitat von erich.wanker (Beitrag 1371724)

Und: Es sind viele Familiennamen und Regions-namen in den Texten - die findet man nicht in einer Wörterbuchliste - und die sind eigentlich meine wichtigsten Indikatoren

[/QUOTE]

Die Arbeit die Listen zu erstellen nimmt die aber niemand ab. Sind ja nur ganz normale Textdateien, und Material findest Du im Internet zu hauf [5][6] und viele mehr.

cu Ha-Jö

[1] https://github.com/tesseract-ocr/tes...ImproveQuality
[2] http://stackoverflow.com/questions/2...seract-library
[3] https://mazira.com/blog/optimal-imag...-tesseract-ocr
[4] https://github.com/chaosben/theunkno...ringSimilarity
[5] http://www.namepedia.org/de/lastname/
[6] http://www.namenforschung.net/dfd/woerterbuch/liste/
[7] https://gedbas.genealogy.net/names/list

erich.wanker 18. Mai 2017 09:23

AW: Text bereinigen: kurze Wörter löschen
 
Hallo und schöne Grüße aus dem Salzburger-Land

VIELEN DANK für die Infos !


Zitat:

Tesseract kann das eigentlich deutlich besser. Wie verwendest Du Tesseract denn, über die Kommandozeile oder als DLL mit der CAPI?
Via Kommandozeile zuerst:

Delphi-Quellcode:
RunProcess(MainForm.datenpfad+'ghostscript\bin\gswin32c.exe -dNOPAUSE -sDEVICE=tiffgray -r300x300 -dBATCH -sPAPERSIZE=a4 -sOutputFile='+tiffname+'Image-%d.tiff '+destname , SW_MINIMIZE, false, ProcID);

Danach:

Delphi-Quellcode:
RunProcess(exepfad+'tesseract\tesseract.exe '+quelle+' '+ziel+' -l deu' , SW_MINIMIZE, true, ProcID);

Die "StringSimilarityRatio" werd ich mir am Wochenende genauer anschauen

Vielen Dank
Erich


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:14 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