31.07.2009

Обработка сфотографированых/отсканированных страниц документов с помощью imagemagick

Есть сфотографированные с экрана документы в формате jpg. Размер файла ~1,5 Мб. Это куски диссертаций сфотографированные в библиотеке. Поскольку фотографировалось "с рук" на всех фото есть черные полосы, само изображение серо-синее.
Задача: сделать страницы более удобочитаемыми и пригодными для печати на принтере.

Сначала решил, что с такой задачей справиться unpaper - unix аналог знаменитого сканкромсатора. Но эксперимент с unpaper показал, что он в этом случае не поможет, слишком плохое качество исходного изображения. Пришлось методом проб и ошибок с помощью утилит imagemagic приводить изображение к приемлемому для печати виду: конвертировать цветное изображение в оттенки серого, повернуть на 90 град, обрезать черные края, увеличить яркость и контраст.

Поэкспериментировав пару часов, написал небольшой скрипт.

#!/bin/bash
echo 'Processing: converting to 8 bit depth'
for f in *; do mogrify -depth 8 $f; done
echo 'done'
echo 'Processing: converting colorspace to grey'
for f in *; do mogrify -colorspace GRAY $f; done
echo 'done'
echo 'Processing: normalizing'
for f in *; do mogrify -normalize $f; done
echo 'done'
echo 'Processing: rotate'
for f in *; do mogrify -rotate "90" $f; done
echo 'done'
echo 'Processing: crop'
for f in *; do mogrify -crop 2040x2990+210+105 $f; done
echo 'done'
echo 'Processing: modulate'
for f in *; do mogrify -modulate 200 $f; done
echo 'done'
echo 'Processing: contrast'
for f in *; do mogrify -contrast -contrast $f; done
echo 'done'


mogrify -depth 8 - на всякий случай конвертирует 16-битное изображение в 8-битное

mogrify -normalize - улучшает контраста на изображении

mogrify -colorspace GRAY - конвертирует цветное изображение в оттенки серого

mogrify -rotate "-90" - поворачивает изображение на 90 град

mogrify -crop 2100x3000+90+270 - обрезка, - задается размер фрагмента, который останется после обрезки 2100x3000 и его смещение относительно левого верхнего угла +90+270, для определения параметров обрезки
(по русски будет так: -crop ШиринаxВысота(конечного_изображения){+-}<Сдвиг_по_Х>{+-}<Сдвиг_по_Y>{%})

display название_файла.jpg щелкнуть левой кнопкой мышки, в появившемся меню пункт Transform, подменю Crop, выделить фрагмент, в левом верхнем углу, под окошком с Crop/Dismis в прямоугольнике и будет то, что нужно в готовом виде 2100x3000+90+270
То же самое можно сделать в Gimp-е там удобнее с масштабом.

mogrify -modulate 200 - увеличивает яркость

mogrify -contrast -contrast - увеличивает контраст (количество опций "-contrast" нужно подбирать от 1 до нескольких)

Для удобства контроля за процессом добавил сообщения:
echo 'Processing: converting colorspace to grey'
благодаря этому четко видно на каком этапе находиться процесс выполнения скрипта.
Иногда достаются уже отсканированные книги с помощью FineReader. Кроме того, что ужасное качество сканов, так еще и tiff получаемый на фыхлопе многофреймовый. Решить эту проблему можно так:
for f in *; do convert $f[0] new/$f; done

[0] - номер фрейма, который нужно извлечь (нумерация конечно же с нуля :)
перед запуском команды нужно создать папку new, куда и будут сохранятся выдранные фреймы из каждого файла

Привожу для сравнения
исходное (сырое) изображение из фотоаппарата


обработанное с помощью скрипта и imagemagick



Внимание! В скрипте используется команда mogrify - она заменяет исходный файл на файл с результатом обработки, поэтому перед началом работы сделайте копию обрабатываемых изображений на тот случай, если вы ошиблись с подбором какого то параметра. Вместо mogrify можно использовать convert, но тогда возникают проблемы с фильтрацией имен файлов, так как после выполнения первой команды в каталоге появятся файлы - результаты ее работы. Можно их складывать в отдельную папку и для следующей команды брать из нее или сортировать имена файлов. Я решил не заморачиваться и оставить все как есть.

Надеюсь мой опыт кому то пригодиться.
Знаю все, что сделал можно было реализовать иначе, поэтому если у кого то есть желание прокомментируйте и расскажите как бы вы решили такую задачу!