История изменений
Исправление Obezyan, (текущая версия) :
Сеть можно обучить и буквам, но суть статьи была не в задаче, а в архитектуре. Я взял самую простую задачу для наглядности и понимания архитектуры.
Если это будет интересно, я разовью дальше биологический подход к созданию архитектур нейронных сетей пока не упремся в необходимость использования нейроморфных процессоров или меня не сожгут на костре противники прогресса из комментариев выше.
Для вашей же прикладной задачи подойдет уже готовое решение без Tesseract, модель Qwen2.5-VL-7B-Instruct (~16Gb). Если есть видеокарта которая потянет модель, то все довольно просто:
#!/usr/bin/env python3
from transformers import Qwen2_5_VLForConditionalGeneration, AutoTokenizer, AutoProcessor
from qwen_vl_utils import process_vision_info
# параметры для изменения
image_path = "/путь/к/вашему/изображению" # можно https://...
max_new_tokens = 1024
model_path_or_name = "Qwen/Qwen2.5-VL-7B-Instruct"
prompt = """
Ты — система оптического распознавания текста (OCR).
Твоя задача - точно извлечь ВЕСЬ текст с предоставленного изображения и сохранить его визуальную структуру.
Правила:
- Переписывай текст дословно, без исправлений, интерпретаций и сокращений
- Сохраняй язык оригинала
- Сохраняй регистр букв
- Сохраняй пунктуацию и специальные символы
- Передавай переносы строк и абзацы
- Сохраняй порядок чтения: сверху вниз, слева направо
- Заголовки, списки и нумерацию сохраняй как в оригинале
- Таблицы оформляй в виде Markdown-таблиц
- Если текст или элемент частично нечитаем — укажи [неразборчиво]
- Если текста на изображении нет — ответь: "Текст не обнаружен"
Вывод:
- Выводи ТОЛЬКО распознанный текст
- Не добавляй комментариев, пояснений или служебных сообщений
"""
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(model_path_or_name, torch_dtype="auto", device_map="auto")
processor = AutoProcessor.from_pretrained(model_path_or_name)
messages = [
{
"role": "user",
"content": [
{
"type": "image",
"image": image_path,
},
{
"type": "text",
"text": prompt
},
],
}
]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pt")
inputs = inputs.to("cuda")
generated_ids = model.generate(**inputs, max_new_tokens=max_new_tokens)
generated_ids_trimmed = [out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)]
output_text = processor.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)
print(output_text)
Скрипт сам скачает модель при первом запуске и выведет весь текст из изображения.
Если нужной карты под рукой нет то можно попробовать ее же на CPU через Ollama указав промт из скрипта в качестве текста вопроса. Учтите что лучше всего модель распознает данные с изображений размером до 1280px, но ничего не мешает закидывать в нее изображения большего размера.
Есть еще state-of-the-art вариант на Qwen 3, но там нужна хорошая видеокарта тк идет связка из двух моделей (embedding и scoring), а сам подход достоин отдельной статьи.
Исправление Obezyan, :
Сеть можно обучить и буквам, но суть статьи была не в задаче, а в архитектуре. Я взял самую простую задачу для наглядности и понимания архитектуры.
Если это будет интересно, я разовью дальше биологический подход к созданию архитектур нейронных сетей пока не упремся в необходимость использования нейроморфных процессоров или меня не сожгут на костре противники прогресса из комментариев выше.
Для вашей же прикладной задачи подойдет уже готовое решение без Tesseract, модель Qwen2.5-VL-7B-Instruct (~16Gb). Если есть видеокарта которая потянет модель, то все довольно просто:
#!/usr/bin/env python3
from transformers import Qwen2_5_VLForConditionalGeneration, AutoTokenizer, AutoProcessor
from qwen_vl_utils import process_vision_info
# параметры для изменения
image_path = "/путь/к/вашему/изображению" # можно https://...
max_new_tokens = 1024
model_path_or_name = "Qwen/Qwen2.5-VL-7B-Instruct"
prompt = """
Ты — система оптического распознавания текста (OCR).
Твоя задача - точно извлечь ВЕСЬ текст с предоставленного изображения и сохранить его визуальную структуру.
Правила:
- Переписывай текст дословно, без исправлений, интерпретаций и сокращений
- Сохраняй язык оригинала
- Сохраняй регистр букв
- Сохраняй пунктуацию и специальные символы
- Передавай переносы строк и абзацы
- Сохраняй порядок чтения: сверху вниз, слева направо
- Заголовки, списки и нумерацию сохраняй как в оригинале
- Таблицы оформляй в виде Markdown-таблиц
- Если текст или элемент частично нечитаем — укажи [неразборчиво]
- Если текста на изображении нет — ответь: "Текст не обнаружен"
Вывод:
- Выводи ТОЛЬКО распознанный текст
- Не добавляй комментариев, пояснений или служебных сообщений
"""
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(model_path_or_name, torch_dtype="auto", device_map="auto")
processor = AutoProcessor.from_pretrained(model_path_or_name)
messages = [
{
"role": "user",
"content": [
{
"type": "image",
"image": image_path,
},
{
"type": "text",
"text": prompt
},
],
}
]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pt")
inputs = inputs.to("cuda")
generated_ids = model.generate(**inputs, max_new_tokens=max_new_tokens)
generated_ids_trimmed = [out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)]
output_text = processor.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)
print(output_text)
Скрипт сам скачает модель при первом запуске и выведет весь текст из изображения.
Если нужной карты под рукой нет то можно попробовать ее же на CPU через Ollama указав промт из скрипта в качестве текста вопроса. Учтите что лучше всего модель распознает данные с изображений размером до 1280px, но ничего не мешает закидывать в нее изображения большего размера.
Есть еще state-of-the-art вариант на Qwen 3, но там нужна хорошая видеокарта тк идет связка из двух моделей (embedding и scoring)? а сам подход достоин отдельной статьи.
Исправление Obezyan, :
Сеть можно обучить и буквам, но суть статьи была не в задаче, а в архитектуре. Я взял самую простую задачу для наглядности и понимания архитектуры.
Если это будет интересно, я разовью дальше биологический подход к созданию архитектур нейронных сетей пока не упремся в необходимость использования нейроморфных процессоров или меня не сожгут на костре противники прогресса из комментариев выше.
Для вашей же прикладной задачи подойдет уже готовое решение без Tesseract, модель Qwen2.5-VL-7B-Instruct (~16Gb). Если есть видеокарта которая потянет модель, то все довольно просто:
#!/usr/bin/env python3
from transformers import Qwen2_5_VLForConditionalGeneration, AutoTokenizer, AutoProcessor
from qwen_vl_utils import process_vision_info
# параметры для изменения
image_path = "/путь/к/вашему/изображению" # можно https://...
max_new_tokens = 1024
model_path_or_name = "Qwen/Qwen2.5-VL-7B-Instruct"
system_prompt = """
Ты — система оптического распознавания текста (OCR).
Твоя задача - точно извлечь ВЕСЬ текст с предоставленного изображения и сохранить его визуальную структуру.
Правила:
- Переписывай текст дословно, без исправлений, интерпретаций и сокращений
- Сохраняй язык оригинала
- Сохраняй регистр букв
- Сохраняй пунктуацию и специальные символы
- Передавай переносы строк и абзацы
- Сохраняй порядок чтения: сверху вниз, слева направо
- Заголовки, списки и нумерацию сохраняй как в оригинале
- Таблицы оформляй в виде Markdown-таблиц
- Если текст или элемент частично нечитаем — укажи [неразборчиво]
- Если текста на изображении нет — ответь: "Текст не обнаружен"
Вывод:
- Выводи ТОЛЬКО распознанный текст
- Не добавляй комментариев, пояснений или служебных сообщений
"""
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(model_path_or_name, torch_dtype="auto", device_map="auto")
processor = AutoProcessor.from_pretrained(model_path_or_name)
messages = [
{
"role": "user",
"content": [
{
"type": "image",
"image": image_path,
},
{
"type": "text",
"text": system_prompt
},
],
}
]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pt")
inputs = inputs.to("cuda")
generated_ids = model.generate(**inputs, max_new_tokens=max_new_tokens)
generated_ids_trimmed = [out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)]
output_text = processor.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)
print(output_text)
Скрипт сам скачает модель при первом запуске и выведет весь текст из изображения.
Если нужной карты под рукой нет то можно попробовать ее же на CPU через Ollama указав системный промт из скрипта в качестве текста вопроса. Учтите что лучше всего модель распознает данные с изображений размером до 1280px, но ничего не мешает закидывать в нее изображения большего размера.
Есть еще state-of-the-art вариант на Qwen 3, но там нужна хорошая видеокарта тк идет связка из двух моделей (embedding и scoring)? а сам подход достоин отдельной статьи.
Исходная версия Obezyan, :
Сеть можно обучить и буквам, но суть статьи была не в задаче, а в архитектуре. Я взял самую простую задачи для наглядности и понимания архитектуры.
Если это будет интересно, я разовью дальше биологический подход к созданию архитектур нейронных сетей пока не упремся в необходимость использования нейроморфных процессоров или меня не сожгут на костре противники прогресса из комментариев выше.
Для вашей же прикладной задачи подойдет уже готовое решение без Tesseract, модель Qwen2.5-VL-7B-Instruct (~16Gb). Если есть видеокарта которая потянет модель, то все довольно просто:
#!/usr/bin/env python3
from transformers import Qwen2_5_VLForConditionalGeneration, AutoTokenizer, AutoProcessor
from qwen_vl_utils import process_vision_info
# параметры для изменения
image_path = "/путь/к/вашему/изображению" # можно https://...
max_new_tokens = 1024
model_path_or_name = "Qwen/Qwen2.5-VL-7B-Instruct"
system_prompt = """
Ты — система оптического распознавания текста (OCR).
Твоя задача - точно извлечь ВЕСЬ текст с предоставленного изображения и сохранить его визуальную структуру.
Правила:
- Переписывай текст дословно, без исправлений, интерпретаций и сокращений
- Сохраняй язык оригинала
- Сохраняй регистр букв
- Сохраняй пунктуацию и специальные символы
- Передавай переносы строк и абзацы
- Сохраняй порядок чтения: сверху вниз, слева направо
- Заголовки, списки и нумерацию сохраняй как в оригинале
- Таблицы оформляй в виде Markdown-таблиц
- Если текст или элемент частично нечитаем — укажи [неразборчиво]
- Если текста на изображении нет — ответь: "Текст не обнаружен"
Вывод:
- Выводи ТОЛЬКО распознанный текст
- Не добавляй комментариев, пояснений или служебных сообщений
"""
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(model_path_or_name, torch_dtype="auto", device_map="auto")
processor = AutoProcessor.from_pretrained(model_path_or_name)
messages = [
{
"role": "user",
"content": [
{
"type": "image",
"image": image_path,
},
{
"type": "text",
"text": system_prompt
},
],
}
]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pt")
inputs = inputs.to("cuda")
generated_ids = model.generate(**inputs, max_new_tokens=max_new_tokens)
generated_ids_trimmed = [out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)]
output_text = processor.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)
print(output_text)
Скрипт сам скачает модель при первом запуске и выведет весь текст из изображения.
Если нужной карты под рукой нет то можно попробовать ее же на CPU через Ollama указав системный промт из скрипта в качестве текста вопроса. Учтите что лучше всего модель распознает данные с изображений размером до 1280px, но ничего не мешает закидывать в нее изображения большего размера.
Есть еще state-of-the-art вариант на Qwen 3, но там нужна хорошая видеокарата тк идет связка из двух моделей (embedding и scoring)? а сам подход достоен отдельной статьи.