Shell Skript für ADF Scanner Fujitsu SP-1120
Geschrieben von Eric Scheibler am 03.07.2021
Kürzlich habe ich einen Fujitsu SP-1120 gekauft, um meinen alten und langsamen Flachbettscanner zu ersetzen. Der Fujitsu ist ein Scanner mit automatischem Dokumenteneinzug (ADF) und Duplex Unterstützung. Er scannt deutlich schneller, erfasst Vorer- und Rückseite auf einmal und liefert eine deutlich bessere Bildqualität und somit erheblich genauere OCR Ergebnisse.
Dieser Artikel enthält eine Installationsanleitung für Debian Linux und ein einfaches Shell Skript, welches einen Scan in eine durchsuchbare PDF Datei konvertiert.
Scanner installieren
Zuerst muss das Linux Treiberpaket heruntergeladen werden. Der Treiber wird offiziell für Ubuntu angeboten, funktioniert aber mindestens auch unter Debian.
Anschließend startet man die Installation:
# dpkg -i pfusp-ubuntu18.04_2.1.1_amd64.deb
und erzeugt die udev Regel 99-fujitsu-sp-1120.rules
unter /etc/udev/rules.d
mit dem folgenden Inhalt:
# Fujitsu ScanSnap SP-1120
ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1473", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes"
Hat man ein anderes Scannermodell wie beispielsweise den SP-1125 oder den SP-1130 gekauft, muss die Produkt-Id angepasst werden. Anschließend die udev Regeln neu laden:
# udevadm control --reload
# udevadm trigger
Schließlich noch sane (Scanner Access Now Easy) installieren und überprüfen, ob der Scanner korrekt erkannt wird:
# apt install sane
# scanadf --list-devices
Die Ausgabe sollte etwa wie folgt aussehen:
device `pfusp:SP1120:001:093' is a FUJITSU SP1120 scanner
Scanskript
Als nächstes das weiter unten angebotene Shell Skript herunterladen, ausführbar machen und ggf. ein paar Variablen anpassen. Beispielsweise habe ich als PDF Betrachter ein anderes Shell Skript von mir angegeben, welches sich hier findet.
Einen Scan startet man anschließend wie folgt:
adf
Der Parameter -p
zeigt eine Vorschau der ersten Seite,
bevor das gesamte Dokument verarbeitet wird und -h
gibt
einen Überblick über alle Funktionen des Skripts.
Download: adf
#!/bin/bash
# Script to control an ADF scanner
# - start scanning and create a single pdf file
# - with empty page and orientation detection
# - tested with Fujitsu SP-1120
#
# ... excessively borrowed from https://github.com/rocketraman/sane-scan-pdf
#
# Version: 0.1
# Date: 2021-06-16
# License: GNU General Public License
# Author: Eric Scheibler
# E-Mail: email [at] eric-scheibler [dot] de
# URL: http://eric-scheibler.de/en/blog/2015/04/script-to-extract-text-from-images-and-scanned-pdf-files/
#
# Install:
# sudo apt install imagemagick poppler-utils sane tesseract-ocr tesseract-ocr-deu tesseract-ocr-eng unpaper
OUTPUT="scan.pdf"
TEXT_EDITOR="/usr/bin/vim"
PDF_VIEWER="$HOME/bin/ocr"
HELP=0
VERBOSE=0
# scanner params
DEVICE=pfusp
RESOLUTION=400
MODE=Lineart
# ocr params
OCR_LANGUAGE=deu
OCR_PREVIEW_FIRST_PAGE=0
OVERWRITE_OUTPUT_FILE=0
#####
TMP_DIR=$(mktemp -d -p "" scan.XXXXXXXXXX)
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
function yes_or_no {
while true; do
read -p "$* [y/n]: " yn
case $yn in
[Yy]*) return 0 ;;
[Nn]*) echo "Aborted" ; return 1 ;;
esac
done
}
# Parse command-line options
while [[ $# > 0 ]]; do
case "$1" in
-h|--help) HELP=1 ;;
-v|--verbose) VERBOSE=1 ;;
-o|--output) shift; OUTPUT="$1" ;;
-x|--device) shift; DEVICE=$1;;
-m|--mode) shift; MODE=$1 ;;
-r|--resolution) shift; RESOLUTION=$1 ;;
-l|--language) shift; OCR_LANGUAGE=$1 ;;
-p|--preview-first-page) OCR_PREVIEW_FIRST_PAGE=1 ;;
-w|--overwrite-output-file) OVERWRITE_OUTPUT_FILE=1 ;;
esac
shift # next option
done
if [[ $HELP == 1 ]]; then
echo "$(basename $0) [OPTIONS]... [OUTPUT]"
echo ""
echo "OPTIONS"
echo " -x, --device"
echo " Override scanner device name, defaulting to \"pfusp\""
echo " -m, --mode"
echo " Mode e.g. Lineart (default), Halftone, Gray, Color, etc."
echo " -r, --resolution"
echo " Resolution e.g 300 (default)"
echo " -l, --language <lang>"
echo " which language to use for OCR"
echo " -p, --preview-first-page"
echo " OCR first page and preview in $TEXT_EDITOR"
echo ""
echo "OUTPUT"
echo " -o, --output <outputfile>"
echo " Output to named file default=scan.pdf"
echo " -w, --overwrite-output-file"
echo " Overwrite the output pdf file, if it already exists"
echo " -v, --verbose"
exit 0
fi
if [[ $VERBOSE == 0 ]]; then
quiet_paran="--quiet"
suppress_error_messages="2> /dev/null"
fi
if [[ "$OUTPUT" == "" ]]; then
echo >&2 "Output file must be specified. Aborting."
exit 1
fi
if [[ -f "$OUTPUT" ]]; then
if [[ $OVERWRITE_OUTPUT_FILE == 0 ]]; then
echo >&2 "Output file $OUTPUT already exists. Aborting."
exit 1
else
rm "$OUTPUT"
fi
fi
echo >&2 "Scanning..."
scanadf --device-name "$DEVICE" --source Adf-duplex --resolution $RESOLUTION --mode $MODE -o $TMP_DIR/scan-%04d
if [[ $? != 0 ]]; then
exit 1
fi
echo ""
shopt -s extglob nullglob
image_files=($TMP_DIR/scan-[0-9]*)
num_scans=${#image_files[@]}
if [[ $num_scans > 0 ]]; then
if [[ $OCR_PREVIEW_FIRST_PAGE == 1 ]]; then
echo "Creating preview..."
preview_image_file="${image_files[0]}"
preview_text_file="$TMP_DIR/preview_first_page.txt"
# ocr
eval tesseract $preview_image_file ${preview_text_file%.*} -l $OCR_LANGUAGE --psm 12 $suppress_error_messages
# show
$TEXT_EDITOR $preview_text_file
if ! yes_or_no "Proceed?"; then
exit 0
fi
# remove preview text file
rm $preview_text_file
echo ""
fi
echo "Processing $num_scans pages"
for image_file in ${image_files[@]}; do
echo "Process $(basename $image_file)"
# unpaper
eval unpaper $quiet_paran --overwrite --dpi $RESOLUTION $image_file $image_file $suppress_error_messages
# convert to tiff
convert -density ${RESOLUTION}x${RESOLUTION} -units PixelsPerInch $image_file ${image_file}.tiff
rm $image_file
# orientation detection
orientation_result=$(eval tesseract ${image_file}.tiff - --psm 0 $suppress_error_messages) || orientation_result=
if [[ $orientation_result == *"Rotate: 180"* ]]; then
echo "Image orientation is upside down, rotate"
convert -rotate 180 ${image_file}.tiff ${image_file}.tiff
fi
# empty page detection
percentage_white=$(convert ${image_file}.tiff -fuzz 0% -negate -threshold 0 -negate -format "%[fx:100*mean]" info:) || percentage_white=0
is_empty_page=$(echo "$percentage_white >= 99.8" | bc -l)
if [[ $is_empty_page == 1 && $orientation_result == "" ]]; then
echo "Empty page removed"
else
eval tesseract ${image_file}.tiff $image_file -l $OCR_LANGUAGE pdf $suppress_error_messages
rm ${image_file}.tiff
fi
echo ""
done
# rename or unite created pdf(s)
pdf_files=($TMP_DIR/scan-[0-9]*.pdf)
num_pdf_files=${#pdf_files[@]}
if [[ $num_pdf_files == 1 ]]; then
echo "Renaming..."
mv $TMP_DIR/scan-0*.pdf "$OUTPUT"
elif [[ $num_pdf_files > 1 ]]; then
echo "Concatenating pdfs..."
pdfunite "${pdf_files[@]}" "$OUTPUT"
fi
fi
if [[ -f "$OUTPUT" ]]; then
echo "Done."
if [[ $PDF_VIEWER != "" ]]; then
if yes_or_no "Open ${OUTPUT}?"; then
$PDF_VIEWER $OUTPUT
fi
fi
else
echo "No scans found."
fi