惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
S
SegmentFault 最新的问题
Schneier on Security
Schneier on Security
W
WeLiveSecurity
Webroot Blog
Webroot Blog
T
Threatpost
量子位
大猫的无限游戏
大猫的无限游戏
C
Cisco Blogs
腾讯CDC
N
News | PayPal Newsroom
T
Troy Hunt's Blog
T
Tailwind CSS Blog
Latest news
Latest news
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The Register - Security
The Register - Security
Know Your Adversary
Know Your Adversary
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Engineering at Meta
Engineering at Meta
SecWiki News
SecWiki News
MyScale Blog
MyScale Blog
GbyAI
GbyAI
Application and Cybersecurity Blog
Application and Cybersecurity Blog
A
Arctic Wolf
The GitHub Blog
The GitHub Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Help Net Security
Help Net Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
有赞技术团队
有赞技术团队
NISL@THU
NISL@THU
L
LINUX DO - 最新话题
雷峰网
雷峰网
P
Privacy International News Feed
Spread Privacy
Spread Privacy
Attack and Defense Labs
Attack and Defense Labs
N
News and Events Feed by Topic
月光博客
月光博客
V
V2EX
H
Help Net Security
博客园 - 三生石上(FineUI控件)
U
Unit 42
B
Blog
PCI Perspectives
PCI Perspectives
G
GRAHAM CLULEY
Stack Overflow Blog
Stack Overflow Blog
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
Last Week in AI
Last Week in AI

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
OneOCR — скрытая OCR внутри Windows 11
AnSa8 · 2026-05-06 · via Все публикации подряд на Хабре

Уровень сложностиПростой

Время на прочтение7 мин

Охват и читатели0

Туториал

OneOCR — это набор из двух динамических библиотек и одной модели ONNX для распознавания текста в приложениях Snipping Tool и Photos в Windows 11.


Скажу сразу: статьи писать я не умею, а воды лить не хочу, поэтому писанины будет немного.

Итак, набор из трёх файлов состоит из: oneocr.dll, onnxruntime.dll и oneocr.onemodel.

Microsoft официально не предоставляет документацию и API к библиотеке OneOCR. Первое упоминание о OneOCR встречается у пользователя github b1tg. Все остальные найденные источники ссылаются на него.

Не знаю точно в какой версии Windows появилась эта функция, но в 23H2 у Snipping Tool 11.2409.25.0 она уже была. Также эти библиотеки и ONNX модель есть и у приложения Photos.

На момент написания статьи у меня в Windows 11 Pro 24H2 (26100.8328) установлены версии Photos 2026.11020.20001.0 и Snipping Tool 11.2601.12.0. При чём версия onnxruntime.dll у Snipping Tool старее (1.19.0.0) чем в Photos (1.23.0.0). Модели также различаются по содержимомоу.

Для примера я буду использовать ту, что посвежее. Замечу, что OneOCR хорошо работает на CPU (даже на моём стареньком Intel Core i3-4170), хотя, судя по релизам onnxruntime и экспортируемой из oneocr.dll функции OcrProcessOptionsSetRunBackendModelOnCPU, может работать и на GPU, но, скажу сразу, задействовать GPU мне не удалось.

Для минимального примера понадобится импортировать всего 5 функций:

result_t CreateOcrPipeline( const char *, const char *, init_options_t, pipeline_t * );
result_t RunOcrPipeline( pipeline_t, const image_t *, process_options_t, instance_t * );
result_t GetOcrLineCount( instance_t, uint64_t * );
result_t GetOcrLine( instance_t, uint64_t, line_desc_t * );
result_t GetOcrLineContent( line_desc_t, const char ** );

result_t — просто 32-битный целочисленный тип, хранящий код ошибки (всего их может быть 8, значения от 0 до 7, где 0 — это успешный результат).

init_options_t, process_options_t, pipeline_t, instance_t и line_desc_t — это указатели на внутренние структуры. Они «непрозрачны» и их содержимое по большому счету неизвестно, да нам оно и не особо-то и интересно, на самом деле.

image_t — структура, хранящая информацию об изображении. Информация о двух полях в этой структуре пока остаётся загадкой, но известно, какие значения они могут принимать и для примера этого хватит. Эксперименты показывают, что изображение должно быть в формате 32bpp (4 байта на пиксель). Причём порядок каналов RGB, как я понял, значения не имеет (ведь какая для ML-модели разница, какой будет текст, синий или красный?).

Простейший пример для лучшего понимания (я намеренно убрал все проверки на ошибки и код освобождения ресурсов):

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincodec.h>
#include <cstdio>
#include <cstdint>

struct image_t {
	uint32_t	type;		// 0, 1, 2, or 3
	uint32_t	width;
	uint32_t	height;
	uint32_t	reserved;	// ???
	uint64_t	stride;
	uint8_t *	data;
}; // struct image_t

using result_t			= uint32_t;
using init_options_t	= void *;
using process_options_t	= void *;
using pipeline_t		= void *;
using instance_t		= void *;
using line_desc_t		= void *;

result_t (__cdecl *CreateOcrPipeline)( const char *, const char *, init_options_t, pipeline_t * );
result_t (__cdecl *RunOcrPipeline)( pipeline_t, const image_t *, process_options_t, instance_t * );
result_t (__cdecl *GetOcrLineCount)( instance_t, uint64_t * );
result_t (__cdecl *GetOcrLine)( instance_t, uint64_t, line_desc_t * );
result_t (__cdecl *GetOcrLineContent)( line_desc_t, const char ** );
void     (__cdecl *ReleaseOcrPipeline)( pipeline_t );

void load_image( const wchar_t * filename, image_t * p_image ) {
	IWICImagingFactory *	p_Factory		= NULL;
	IWICBitmapDecoder *		p_Decoder		= NULL;
	IWICBitmapFrameDecode *	p_Frame			= NULL;
	IWICBitmapSource *		p_BitmapSource	= NULL;
	IWICFormatConverter *	p_Converter		= NULL;
	IWICBitmapSource *		p_Result		= NULL;

	CoInitialize( NULL );
	CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS( &p_Factory ) );
	p_Factory->CreateDecoderFromFilename( filename, NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &p_Decoder );
	p_Decoder->GetFrame( 0, &p_Frame );
	p_Frame->QueryInterface( IID_IWICBitmapSource, reinterpret_cast<void **>(&p_BitmapSource) );

	p_Frame->GetSize( &p_image->width, &p_image->height );
	p_image->stride	= p_image->width * 4;
	p_image->data	= new uint8_t [p_image->stride * p_image->height];

	WICPixelFormatGUID pixel_format;
	p_Frame->GetPixelFormat( &pixel_format );

	// Convert format to GUID_WICPixelFormat32bppRGB...
	if ( pixel_format != GUID_WICPixelFormat32bppRGB ) {
		p_Factory->CreateFormatConverter( &p_Converter );
		p_Converter->Initialize( p_BitmapSource, GUID_WICPixelFormat32bppBGR, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeCustom );
		p_Converter->QueryInterface( IID_PPV_ARGS( &p_Result ) );
	}

	p_Result->CopyPixels( NULL, p_image->stride, p_image->stride * p_image->height, reinterpret_cast<BYTE *>( p_image->data ) );
}

int main( int argc, char * args[] ) {
	SetConsoleOutputCP( CP_UTF8 );

	if ( argc != 2 ) {
		printf( "Use: %s image_filename\n", args[0] );
		return 1;
	}

	HMODULE	dll = LoadLibrary( "oneocr.dll" );

	CreateOcrPipeline	= (decltype( CreateOcrPipeline ))GetProcAddress( dll, "CreateOcrPipeline" );
	RunOcrPipeline		= (decltype( RunOcrPipeline    ))GetProcAddress( dll, "RunOcrPipeline" );
	GetOcrLineCount		= (decltype( GetOcrLineCount   ))GetProcAddress( dll, "GetOcrLineCount" );
	GetOcrLine			= (decltype( GetOcrLine        ))GetProcAddress( dll, "GetOcrLine" );
	GetOcrLineContent	= (decltype( GetOcrLineContent ))GetProcAddress( dll, "GetOcrLineContent" );

	// Convert image path to wide-char for image loader...
	wchar_t	w_filename[MAX_PATH] = {};
	swprintf( w_filename, MAX_PATH, L"%s", args[1] );

	image_t image = { 3/*type*/ };
	load_image( w_filename, &image );

	pipeline_t pipeline = nullptr;
	CreateOcrPipeline( "oneocr.onemodel", "kj)TGtrK>f]b[Piow.gU+nC@s\"\"\"\"\"\"4", nullptr/*init options*/, &pipeline );

	instance_t instance = nullptr;
	RunOcrPipeline( pipeline, &image, nullptr/*process options*/, &instance );

	uint64_t n_lines = 0;
	GetOcrLineCount( instance, &n_lines );

	for ( int i = 0; i < n_lines; i++ ) {

		// Get line descriptor...
		line_desc_t line_desc = nullptr;
		GetOcrLine( instance, i, &line_desc );
		if ( line_desc ) {

			// Get null-terminated line ptr...
			const char * line_ptr = nullptr;
			GetOcrLineContent( line_desc, &line_ptr );
			printf( " %s\n", line_ptr );
		}

	}
	return 0;
}

Код элементарный, комментировать тут особо нечего.

Пара примеров распознавания рукописного текста (я человек простой, поэтому примеры изображений стащил из чужой статьи 2025-го года):

Скрытый текст
 Привет. Это образен для распознавания
 ТЕкстА ДЛя сТАТьИ в Т-Ж. ПровЕрим
 сколько слов он определит полностью,
 >
 сколько прЕврАтит в нАБор Букв и
 сколько вообш,Е нЕ узнаЕт:
 1. Набор слов для распознавания №1.
 2. Ещё один набор слов.
 3. Третий набор слово.
 4. Экспрессия-четвертое слово.
 5. Финальное пятое слово.
Скрытый текст
 Я вас любил: любовь ещё, быть может
 В душе моей учасла не совсем;
 пусть она вас большше не тревожит;
 Я не хочу печалить вас ничим.
 Я вас любии безлитивно, безна дежно,
 По рабостью, то равностью тамим;
 Я вас любил этал искренно, ток нежно,
 Как дай вам Бы любимой быть другим.

Ну и один пример распознавания печатного текста (изображение было взято где-то в сети интернет):

Скрытый текст
 В богатовских садах
 Рассказ
 М.С.Богатовец
 Начиная, от Панфилихи по обрывистому берегу Северного Донца в
 протяжении двух километров тянутся богатовские сады. Это одно из бо-
 гатых мест хутора. Оно всегда привлекало на себя внимание не только
 народа, но и перелетную птицу, полевых зверей и охотников на чужое
 добро. В летнее время по садам кочуют косяками дворовые подростки.
 Они охотятся на сорочиные яйца, касачек, сизокрылых шнурков. Купают-
 ся в Донце и исподволь пасутся по чужому крыжовнику. Свежий ветерок
 из Донца покачивает богатые деревья фруктами: яблоками, сливами, гру-
 шами и обильной вишней.
 ***
 В истории прошлого, участки садов передавались из рук в руки по на-
 следству. Местные жители хорошо возделывают землю под садами. На
 зиму или весной земля вскапывается. Нижние части плодородных ство-
 лов наносятся известью, для борьбы с вредителями. А сухие деревья
 уничтожаются и используются для топлива. Стены садов слегка ремонти-
 руются, как ограждение от бродящего скота.
 Сады всячески охраняются, особенно в весеннее время. Осенью, ког-
 да все с садов убрано, в ночное время некоторые жители позволяют себе
 и запускают скот для откормки. Однако, это в ущерб садам, и в этот пери-
 од некоторые более трудолюбивые хозяева усиливают ограждение. Над-
 сматривают над своим салом и порыкивают на свиней и скотину.
 ***
 В особенности привлекательны сады в весеннее время, когда зелень
 в полном своем расцвете. С садов доносится в хутор несмолкаемый пти-
 чий гам. Поют, где-то в поднебесьях соловьи. Пророчат вечно перелетные
 кукушки. Пыхтят на каменных стенах пастушки со своим острым гребнем.
 Летают и пересаживаются из стены на стену чикалки, помахивая сво-
 им сереньким хвостом. Пролетают над головами, на большой скорости
 скворцы. Они направляют свой путь в колки, где им привольно и обилье
 корма. Воркуют горлинки по своим детям. Эта одна из бедных несушек
 в наших садах, которая не в состоянии даже сделать, как следует себе
 гнездышко. Пролетают над садами дикие утки. Их полет напоминает ле-
 тевшую со свистом бомбу. Где-то далеко в садах назойливо поет иволга.
 Летят сороки по направлению хутора на охоту на цыплят. Ее небольшие
 крылья стягивают к себе воздух. Сзади широкий разлатый хвост, регули-
 рует свое направление. Черные галки сидят на вершинах тополей и ос-
 матривают окружение. По Дону, шлепая полостями, поднимается в гору
 пароход с баржами, и выпущенным черным дымом покрывает сады.
 ***
 Пестреющий в садах народ, как и птица, каждый занят своим делом.
 Одни полют высоко поднявшуюся траву. Другие, закутав нос платком от
 назойливых комаров, рвут вишню завтра к базару. Третьи чинят изгородь,
 рвут калюку и накладывают на стену. Четвертые, расположившись под

Пример выше и более правильная реализация (с проверками ошибок и т. п.) находятся на GitHub

Ссылки на первоисточники