Δίγλωσσος εμπλουτισμός σαρωμένων αρχείων pdf με δυνατότητα αναζήτησης κειμένου (pdfocr, tesseract OCR)

Προβληματισμός, προτάσεις και λύσεις για "αναβάθμιση" του Η/Υ σε εργαλείο παραγωγικότητας!
Λειτουργικά συστήματα, Backup/Recovery, χρήση του hardware I/O.
Απάντηση
Άβαταρ μέλους
GeorgeVita
Διαχειριστής
Δημοσιεύσεις: 637
Εγγραφή: 04 Σεπ 2013, 21:51
Ονομα: Γιώργος
Επικοινωνία:

Δίγλωσσος εμπλουτισμός σαρωμένων αρχείων pdf με δυνατότητα αναζήτησης κειμένου (pdfocr, tesseract OCR)

Δημοσίευση από GeorgeVita »

Δίγλωσσος εμπλουτισμός σαρωμένων αρχείων pdf με δυνατότητα αναζήτησης κειμένου (pdfocr, tesseract OCR)

Με αφορμή ένα αρχείο pdf στο θέμα "Πραγματικές Κεραίες", ασχολήθηκα με την επεξεργασία και τον εμπλουτισμό ενός scan-αρισμένου αρχείου pdf ώστε να αποκτήσει δυνατότητα αναζήτησης και επιλογής κειμένου στα Ελληνικά και τα Αγγλικά. Στην αναζήτηση για λύσεις Open Source βρήκα το pdfocr (script σε γλώσσα RUBY) το οποίο με λίγες προσαρμογές έδωσε ένα καλό αποτέλεσμα. Το αρχείο της δοκιμής ήταν αρκετά μεγάλο, 188 σαρωμένες σελίδες, αλλά ο χρόνος μετατροπής των 30 λεπτών μου φάνηκε μεγάλος για ένα σύγχρονο Η/Υ. Ετσι έψαξα τρόπους βελτίωσης του pdfocr script.

Σημείωση: χρησιμοποίησα το pdfocr.rb ver. 0.1.4 Copyright (c) 2010 Geza Kovacs

Αρχικά ανέλυσα τον τρόπο λειτουργίας του pdfocr επιλέγοντας τις εντολές και τα προγράμματα που επέτρεπαν δίγλωσση αναγνώριση OCR. Συνοπτικά τα βήματα/εντολές που εκτελεί το pdfocr για την επεξεργασία του example.pdf και παραγωγή του εμπλουτισμένου αρχείου final.pdf είναι:

Κώδικας: Επιλογή όλων

# pdfocr CLI steps using pdftk, pdftoppm, tesseract
# simplified by GeorgeVita (7-JAN-2017)
# from pdfocr.rb ver 0.1.4 Copyright (c) 2010 Geza Kovacs
#
pdftk example.pdf dump_data > pdfinfo.txt
pdftk example.pdf cat 5 output page005.pdf
pdftoppm -r 300 page005.pdf >page005.ppm
tesseract -l ell+eng page005.ppm page005_new pdf
pdftk *_new.pdf cat output merged.pdf
pdftk merged.pdf update_info pdfinfo.txt output final.pdf
#
# finally, delete all intermediate files
Στο παράδειγμα έχω εντολές για εξαγωγή/μετατροπή (δίγλωσση) της 5ης σελίδας του αρχείου example.pdf με χρήση ανάλυσης 300 DPI. Στο προτελευταίο βήμα γίνεται συνένωση όλων των αρχείων με κατάληξη _new.pdf. Δεν δείχνω τις εντολές διαγραφής των ενδιάμεσων αρχείων.

Απαιτούμενα προγράμματα για τα βήματα/εντολές του παραδείγματος:
tesseract-ocr, pdftoppm, pdftk και το αρχείο ελληνικών: tesseract-ocr-ell

Για να τρέξει το αρχικό script (pdfocr.rb) με δίγλωσση μετάφραση σε Ubuntu χρειάζονται:
- pdfocr (https://github.com/gkovacs/pdfocr)
- ruby, tesseract-ocr, tesseract-ocr-ell, pdftoppm, pdftk
- αλλαγή στη γραμμή #73 του pdfocr.rb από language = 'eng' σε language = 'ell+eng'
- εκκίνηση από το directory του pdfocr.rb με:
ruby pdfocr.rb -i example.pdf -o final.pdf


Σχετικά:
- PDFtk, παραδείγματα για τερματικό, PDFtk free for Windows (XP, 7, 8)
- Xpdf
- pdftoppm manual (Ubuntu)
- Tesseract OCR manual, command line usage
Άβαταρ μέλους
GeorgeVita
Διαχειριστής
Δημοσιεύσεις: 637
Εγγραφή: 04 Σεπ 2013, 21:51
Ονομα: Γιώργος
Επικοινωνία:

Δίγλωσσος εμπλουτισμός σαρωμένων αρχείων pdf με δυνατότητα αναζήτησης κειμένου (pdfocr, tesseract OCR)

Δημοσίευση από GeorgeVita »

Μετά την ανάλυση και την επιβεβαίωση μέσω τερματικού για τα βήματα/εντολές μετατροπής, έκανα μια προσπάθεια βελτίωσης και επιτάχυνσης της διαδικασίας με τη χρήση περισσότερων πυρήνων του επεξεργαστή. Η υλοποίηση έγινε σε linux bash script και η απόδοση ήταν η αναμενόμενη με χρόνο μετατροπής 9 λεπτά αντί των 30 με το pdfocr (σύστημα Η/Υ με AMD A10-8750).

Το παραθέτω ως version 0.0 επειδή περιέχει εντολές διαγραφής αρχείων μέσα στο προσωρινό ευρετήριο και μπορεί να μου έχει ξεφύγει κάτι...

pdfocr_G.bash ver.0.0

Κώδικας: Επιλογή όλων

#!/bin/bash
echo
echo "-------------"
echo "pdfocr_G.bash (by GeorgeVita, 8-Jan-2017) based on pdfocr ver 0.1.4 Copyright (c) 2010 Geza Kovacs"
echo "-------------"
time_program_started=$SECONDS
if [ -z "$1" ] || [ -z "$2" ]
then 
	echo "Usage: bash $0 source.pdf output.pdf [DPIresolution]"
	echo "Example: bash $0 mybook.pdf mynewbook.pdf 200"
	echo "(default resolution is 300 DPI)"
	exit
fi

if [ -z "$3" ]
then
	res_DPI=300
else
	res_DPI=$3
fi

file_source=$1
file_output=$2
processes_no=$(($(nproc)*2))
temp_dir="./tmp_pdfocr/"
file_pdfinfo=pdfinfo.txt

#pdftk example.pdf dump_data > pdfinfo.txt
page_count=$(pdftk $file_source dump_data | tee $file_pdfinfo | grep PageMediaNumber | wc -l)

if [ $((page_count)) -eq "0" ] ; then
	echo "empty or wrong file!"
	exit
fi

echo "Will be used $processes_no processes for a total of $page_count pages, resolution set to $res_DPI DPI."
echo "-------------"
echo "---> Creation of the temporary directory $temp_dir to store intermediate files."
mkdir -p $temp_dir
echo "---> Clean up $temp_dir in case of previous unfinished conversions."
rm -f $temp_dir*
echo "---> Move pdf info to temporary directory."
mv $file_pdfinfo $temp_dir

#pdftk example.pdf cat 5 output page005.pdf
time_loop_started=$SECONDS
page_no=1
while [[ $page_no -le $page_count ]]
do
	file_out="page"$(printf "%04d" $page_no)".pdf"
	echo -ne '\r'"---> Extracting page $page_no/$page_count to $file_out"
	pdftk $file_source cat $page_no output $temp_dir$file_out &
	((page_no = page_no + 1))
	while [ $( ps -A | grep -i pdftk | wc -l) -ge $processes_no ]
	do
		dummy=1
	done
done
echo -ne ", working, "
wait
time_loop_ended=$SECONDS
time_elapsed=$(($time_loop_ended - $time_loop_started))
echo "finished in $time_elapsed Sec"

#pdftoppm -r 300 page005.pdf >page005.ppm
time_loop_started=$SECONDS
page_no=1
while [[ $page_no -le $page_count ]]
do
	file_pdf="page"$(printf "%04d" $page_no)".pdf"
	file_ppm="page"$(printf "%04d" $page_no)".ppm"
	echo -ne '\r'"---> Converting ($(($res_DPI))DPI) $file_pdf to $file_ppm"
	pdftoppm -r $res_DPI $temp_dir$file_pdf >$temp_dir$file_ppm &
	((page_no = page_no + 1))
	while [ $( ps -A | grep -i pdftoppm | wc -l) -ge $processes_no ]
	do
		dummy=1
	done
done
echo -ne ", working, "
wait
time_loop_ended=$SECONDS
time_elapsed=$(($time_loop_ended - $time_loop_started))
echo "finished in $time_elapsed Sec"

#tesseract -l ell+eng page005.ppm page005_new pdf

time_loop_started=$SECONDS
page_no=1
while [[ $page_no -le $page_count ]]
do
	file_ppm="page"$(printf "%04d" $page_no)".ppm"
	file_newpdf="newpage"$(printf "%04d" $page_no)
	echo -ne '\r'"---> OCR into $file_ppm, create $file_newpdf.pdf"
	tesseract -l ell+eng $temp_dir$file_ppm $temp_dir$file_newpdf pdf 1>/dev/null 2>&1 &
	((page_no = page_no + 1))
	while [ $( ps -A | grep -i tesseract | wc -l) -ge $processes_no ]
	do
		sleep 1
	done
done
echo -ne ", working, "
wait
time_loop_ended=$SECONDS
time_elapsed=$(($time_loop_ended - $time_loop_started))
echo "finished in $time_elapsed Sec"

#pdftk *_new.pdf cat output merged.pdf
echo "---> Merge *_new.pdf files to merged.pdf"
file_out=merged.pdf
files_selected="newpage*"
pdftk $temp_dir$files_selected cat output $temp_dir$file_out

#pdftk merged.pdf update_info pdfinfo.txt output final.pdf
echo "---> Update pdf info using file_pdfinfo, create $file_output."
pdftk $temp_dir$file_out update_info $temp_dir$file_pdfinfo output $file_output

echo "---> Delete all intermediate files."
rm -f $temp_dir*
echo "---> Delete temporary directory."
rmdir $temp_dir

time_program_ended=$SECONDS
time_elapsed=$(($time_program_ended - $time_program_started))
printf 'Total program runtime: %02d:%02d:%02d\n' $(($time_elapsed/3600)) $(($time_elapsed%3600/60)) $(($time_elapsed%60))
echo

Η χρήση του στο αρχείο δοκιμών των 188 σελίδων:

Κώδικας: Επιλογή όλων

$ bash pdfocr_G.bash pgt3.pdf pgt29.pdf
-------------
pdfocr_G.bash (by GeorgeVita, 8-Jan-2017) based on pdfocr.rb ver 0.1.4 Copyright (c) 2010 Geza Kovacs
-------------
Will be used 8 processes for a total of 188 pages, resolution set to 300 DPI.
-------------
---> Creation of the temporary directory ./tmp_pdfocr/ to store intermediate files.
---> Clean up ./tmp_pdfocr/ in case of previous unfinished conversions.
---> Move pdf info to temporary directory.
---> Extracting page 188/188 to page0188.pdf, working, finished in 22 Sec
---> Converting (300DPI) page0188.pdf to page0188.ppm, working, finished in 32 Sec
---> OCR into page0188.ppm, create newpage0188.pdf, working, finished in 481 Sec
---> Merge *_new.pdf files to merged.pdf
---> Update pdf info using file_pdfinfo, create pgt29.pdf.
---> Delete all intermediate files.
---> Delete temporary directory.
Total program runtime: 00:08:58
$
Άβαταρ μέλους
GeorgeVita
Διαχειριστής
Δημοσιεύσεις: 637
Εγγραφή: 04 Σεπ 2013, 21:51
Ονομα: Γιώργος
Επικοινωνία:

Εμπλουτισμός σαρωμένων αρχείων pdf με δυνατότητα αναζήτησης κειμένου (pdfocr, tesseract OCR)

Δημοσίευση από GeorgeVita »

Η παραπάνω διαδικασία είναι πολύ χρήσιμη όταν ψάχνεις την άκρη σε παλιά Service Manual!
Αν υπάρχει ήδη σε .pdf μάλλον είναι σύνολο scan-αρισμένων jpg. Αν είναι σε έντυπη μορφή, με προσεκτικό scan-άρισμα γίνεται αμέσως pdf με δυνατότητα αναζήτησης.

Βέβαια εδώ θα χρειαστούμε απλή μετατροπή μόνο από αγγλικά.
Για να έχουμε εμπλουτισμό κειμένου σε μια γλώσσα (π.χ. αγγλικά) θα αφαιρέσουμε από την εντολή tesseract το "ell+", δηλαδή θα γίνει:

Κώδικας: Επιλογή όλων

   tesseract -l eng $temp_dir$file_ppm $temp_dir$file_newpdf pdf 1>/dev/null 2>&1 &
Αν έχεις ένα καλά scan-αρισμένο αρχείο pdf, τότε μπορείς να βρεις τα εξαρτήματα ακόμη και στο θεωρητικό ή την πλακέτα.
Μπορούμε να δοκιμάσουμε και μια μεγαλύτερη ανάλυση επεξεργασίας (παράδειγμα για 600dpi):

Κώδικας: Επιλογή όλων

bash pdfocr_G.bash ServiceManual.pdf ServiceManual_new.pdf 600
Προσοχή: μεγαλύτερη ανάλυση σημαίνει περισσότερος χρόνος επεξεργασίας και ογκώδες παραγόμενο αρχείο.

Σημειώνω πάλι τα προ-απαιτούμενα προγράμματα για να λειτουργήσει το pdfocr_G.bash (για δίγλωσσο):

Κώδικας: Επιλογή όλων

sudo apt install tesseract-ocr
sudo apt install tesseract-ocr-ell
sudo apt install pdftk
Αν λείπει το pdftoppm θα εγκατασταθεί και το poppler-utils.
Απάντηση

Επιστροφή στο “Ο Η/Υ ως εργαλείο παραγωγικότητας!”