Комментарии 27
Вот в таких задачах ИИ должен идеально работать. И перевести весь скан в распознанный документ. При то с нужным форматированием абзацев, отступов и прочего.
Ну при чем тут ИИ? Статья про GIMP.
Я думал про обработку сканов. Видимо ошибся. Прошу прощения.
Нет, не ошибся. И ежели бы выложил ссылку на статью, в которой ИИ решает эту же, или похожую задачу, то был бы по теме. Но этого то и нету.
Так что тут нового? Условный ФайнРидер это делает уже более 10 лет. Уж не знаю, с ИИ или без ИИ, но делает. И делает если не отлично, то хорошо. Наверное, и другие аналоги уже подтянулись. А уж для современных технологий эта задача должна быть совсем тривиальной, про что в комментарии и написал.
ИИ может быть средне-хорош в болтологии и разных написаниях кода, но для таких задач он может быть идеален.
Так и не вижу ни одной ссылки ни на GIMP, ни на решение данной задачи иными средствами. Не по теме. Я бы сказал даже не близко к статье.
а там(то о чем вы в той степи) впринципе ее так и делают на известных языках(я на java тыкал - работало), уже ИИ есть по распознованию, тоесть определив текст она либо напечатает по новой либо вырежет как в скане, вы наверно хотите не нативную ИИ(клоню к тому что тут она дообучивается от промптов, а там уже в матрицу заложен сам нюанс определения), а по промпту(там где к концу подставляется искомое и ИИ обучается помните было такое, да и щас наверно есть)
Результат применения данного метода: Щавелев Алексей Федорович "Геодезия", 1962.
Спорные улучшения, за OCR не скажу, а глазами текст с исходной картинки, как будто, легче читается - видимо, глазу проще игнорировать визуальные излишества в виде шума, чем достраивать визуальные изъяны в виде погрызенных алгоритмами элементов буков.
Медианный фильтр, понятно, не будет работать - слишком тонкие буквы, и по той же причине не будет работать dilate/erode. Какого-нибудь фильтра на connected components нет в GIMP-е? Типа (не GIMP, конечно, но чем могу):
import cv2
import numpy as np
img_gs = cv2.imread("original.png", cv2.IMREAD_GRAYSCALE)
# чем выше - тем больше шума останется, но нам пофиг -
# шум мелкий, удалим через фильтр по площади
threshold_value = 200
_, img_bw = cv2.threshold(img_gs, threshold_value, 255, cv2.THRESH_BINARY_INV)
analysis = cv2.connectedComponentsWithStats(img_bw, 4, cv2.CV_32S)
n_labels, label_ids, values, _ = analysis
output = np.zeros(img_gs.shape, dtype = np.uint8)
# 1 - объединяем все компоненты с площадью больше пороговой
area_threshold = 10
for i in range(1, n_labels):
area = values[i, cv2.CC_STAT_AREA]
if area > area_threshold:
mask = (label_ids == i).astype(np.uint8) * 255
output = cv2.bitwise_or(output, mask)
result = cv2.bitwise_not(output)
cv2.imwrite("output.png", result)
# 2 - чуть растопырив полученный выше результат, используем его
# как маску для исходного изображения, получая "антиалиасинг"
img_inv = cv2.bitwise_not(img_gs)
result2 = cv2.bitwise_and(img_inv, img_inv, mask = cv2.dilate(output, np.ones((3, 3))))
cv2.imwrite("output2.png", cv2.bitwise_not(result2))Если поставить побольше значение для area_threshold, можно избавиться вообще от всего шума (но заодно и от всех знаков препинания - хотя эта проблема вряд ли вообще решаема исключительно в парадигме фильтрации изображений).

Чтобы глазами приятней читать, можно чуть размазать этот результат и использовать в качестве маски на исходном изображении (см. # 2):

На обложке и медианный фильтр, мне кажется, должен неплохо работать.
"Медианный фильтр" на обложке радиусом 3:

Как то не очень, мелкий текст "всмятку". И ни разу не решает проблему иллюстраций среди текста. Возможно стоит использовать медиану для замены областей, но не в чистом виде.
Использование "Медианного фильтра" радиусом 4 для замены областей вне зон контуров:

Но такая опция упоминается в конце статьи.
Фиг знает, по-моему, как минимум, не хуже последней картинки из поста. Но в обложке цвета присутствуют, её, вероятно, логичнее в HSV разложить (или ещё во что-нибудь) и по H пофильтровать (или по ещё чему-нибудь). Для чёрно-белых иллюстраций из тонких линий, которые, вероятно, и встречаются в тексте, понятно, медианный фильтр не сработает, как и для самого текста.
Можно полностью избавиться от цикла for, использовав np.isin для меток.
фильтровать тоже можно без if с np.nonzero/np.flatnonzero
Так нормально? В смысле, цикл со всем содержимым на это заменить, результат идентичен:
areas = values[:, cv2.CC_STAT_AREA] - area_threshold
areas[0] = 0 # шоб не мешала
area_indices = np.nonzero(areas > 0)
output = np.isin(label_ids, area_indices).astype(np.uint8) * 255Да, так будет быстрее.
Хотя тоже чуть сократить можно.
area_indices=np.nonzero(values[:, cv2.CC_STAT_AREA]> area_threshold)
output = np.isin(label_ids, area_indices[1:]).astype(np.uint8) * 255
Процитирую себя же: "На этом как бы всё. Но! Разговор был так же за иллюстрации. Поэтому продемонстрирую данную методу на участке зашумлённого скана обложки"
Ещё раз процитирую себя же: "Можно применять не только "Гауссово размывание", а любое размывание из "Фильтры"->"Размытие". Так же нет ограничение на то, что использовать для замены зон вне зон контуров."
И ещё раз процитирую себя же: "Использование "Медианного фильтра" радиусом 4 для замены областей вне зон контуров"
Что с иллюстрациями в тексте делать? Точнее, как чистить текст при наличии иллюстраций?
При чём тут DjVu? GIMP же!
Ежели есть какое решение задачи другими инструментами, выкладывайте ссылку.
И? Где решение данной или похожей задачи?
Вас под дулом пистолета заставляют писать сюда комментарии? Вы теперь решаете, какие кому оценки ставить и за что?
Статья про GIMP и решение определённой задачи в нём. Выше люди написали решение задачи другими средствами. К ним претензий нет. К вам есть.
Использование "Медианы" радиусом 3 вместо первого "Гауссового размывания" на том же материале:



GIMP: понижение шума по маске