maXbox Starter 103 — Распознавание текста символов на изображениях.

"Одна картинка стоит тысячи слов. Интерфейс стоит тысячи картинок».

Этот API распознает и читает текст, встроенный в изображения или фотографии. Image to Text API использует механизм OCR на основе нейронной сети (LSTM), который ориентирован на распознавание строк, но также поддерживает распознавание шаблонов символов. Он поддерживает как рукописный текст, так и печатные материалы, а также карты улиц.

APILayer — это торговая площадка API, где ваш API также может охватить более широкую аудиторию, но сначала вам нужен бесплатный API-ключ:

Результатом простой подписки будет скриншот ниже:

Этот регистр позволяет ежемесячно использовать 30 успешных вызовов. Почти все API имеют бесплатный план подписки. Глядя на следующую обложку книги, она легко извлечет текстовую информацию, даже если обложка имеет тени и расположена под углом.

Мы используем библиотеку WinHttp.WinHttpRequest, JSONObjects и TGraphics с загрузкой и тестированием REST-клиента. Также мы передаем API-ключ в виде запроса-заголовка, поэтому сначала получите ключ по адресу: https://apilayer.com/marketplace.

Вы также можете использовать мощную функцию «OCR» (распознавание текста в изображении) для извлечения текста из изображения в процессе преобразования. В этом случае в результате вы получите редактируемый текстовый документ, который сможете корректировать и модифицировать по своему усмотрению.

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

function Image_to_text_API2(AURL, url_imgpath, aApikey: string): string;
var httpq: THttpConnectionWinInet;
    rets: TStringStream;  
    heads: TStrings; iht:IHttpConnection2; 
begin
  httpq:= THttpConnectionWinInet.Create(true); 
  rets:= TStringStream.create('');
  heads:= TStringlist.create;     
   try 
     heads.add('apikey='+aAPIkey);
     iht:= httpq.setHeaders(heads);
     httpq.Get(Format(AURL,[url_imgpath]),rets);
     if httpq.getresponsecode=200 Then result:= rets.datastring
       else result:='Failed:'+
             itoa(Httpq.getresponsecode)+Httpq.GetResponseHeader('message');
   except  
     writeln('EWI_HTTP: '+ExceptiontoString(exceptiontype,exceptionparam));
   finally
     httpq:= Nil;
     heads.Free;
     rets.Free;
   end;                  
end;

Функция основной части открывает соединение, вызывает API и возвращает поток, который мы конвертируем в строку данных.

Живая демонстрация Image2Text или Image to Text предоставляет услугу API на своей платформе публикации APILayer. Функция Live Demo позволяет протестировать API в вашем браузере; не нужно ничего устанавливать или кодировать. Вы можете изменить все параметры по своему усмотрению и взаимодействовать с API на многих языках. Формат экспорта API — JSON, например. обложку нашей книги смотрите ниже:

Опубликованные наборы данных результатов основаны на LSTM в сочетании с OCR. LSTM означает долговременную кратковременную память и является типом рекуррентной нейронной сети (RNN).

Говоря о RNN, это сеть, которая работает с текущим вводом, принимая во внимание предыдущий вывод (обратная связь) и сохраняя в своей памяти в виде ячеек памяти в течение короткого периода времени (кратковременная память). Например, возьмем обложку нашей книги в качестве входных данных:

LSTM имеют связи и ячейки с обратной связью, которые отличают их от более традиционных нейронных сетей с прямой связью с все еще существующей проблемой исчезающего градиента. Это свойство позволяет LSTM обрабатывать целые последовательности данных (например, временные ряды, почерк или предложения) без независимой обработки каждой точки в последовательности, а, скорее, сохраняя полезную информацию о предыдущих данных в последовательности, таких как «объективное ориентирование», «моделирование», « und», «entwickeln» в качестве контекста. Результат вызова

writeln(Image_to_text_API2(URL_APILAY, URLIMAGEPATH4,
‘DNwCF9Rf6y1AmSSednjn8ZhAxYXr — — ‘));

это строка данных JSON в Runtime: 0:0:3.859:

{"lang": "de", "all_text": "ih \ u00bb Der Entwickler\nFachwissen für Programmierer\nMax Kleiner\nUML\nmit Delphi\nОбъектно-ориентированное моделирование\nund entwickeln\nПрограммное обеспечение и поддержка", "аннотации": [ «ih», «bb», «Der», «Entwickler», «Fachwissen», «fcr», «Programmierer», «Max», «Kleiner», «UML», «mit», «Delphi» , «Объектирование», «моделировать», «und», «entwickeln», «Software», «&», «Support»]}

Также в хорошо известный Tesseract 4.0 (как и в OmniPage) добавлен новый механизм OCR на основе нейронных сетей LSTM.

API также можно активировать с помощью нескольких строк кода P4D:

procedure PyCode(imgpath: string);
begin
  with TPythonEngine.Create(Nil) do begin
  pythonhome:= 'C:\Users\max\AppData\Local\Programs\Python\Python36-32\';
  try
    loadDLL;
    ExecString('import requests');
    ExecStr('url= "https://api.apilayer.com/image_to_text/url?
                                                   url='+imgpath+'"'); 
    ExecStr('payload = {}');  
    ExecStr('headers= {"apikey": "dy5L70eQx72794XBZ8sewEgYTZR85----"}'); 
    Println(EvalStr('requests.request("GET",url, headers=headers,
                                                data=payload).text'));  
  except
    raiseError;        
  finally 
    unloadDLL;      
    free;
  end; 
 end;
end;

Когда вы терпите неудачу с ограниченным вызовом или недопустимым ключом, вы получаете кучу исключений, таких как следующие:

winininet_error: Несанкционировано (401). или {"сообщение": "Неверные учетные данные для аутентификации"

Тот факт, что код ошибки не является «одним из ожидаемых возвращаемых значений», говорит для версий, что ошибка исходит из базового уровня, и этот API просто пропускает ее при внутреннем сбое.

Чтобы пролить немного больше света на эти ошибки, существует функция для преобразования ErrorCode в строку для лучшего понимания:

function GetWinInetError(ErrorCode:Cardinal): string;
const
   winetdll = 'wininet.dll';
var
  Len: Integer;
  Buffer: PChar;
begin
  Len:= FormatMessage(
  FORMAT_MESSAGE_FROM_HMODULE or FORMAT_MESSAGE_FROM_SYSTEM or
  FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_IGNORE_INSERTS or
  FORMAT_MESSAGE_ARGUMENT_ARRAY,
  Pointer(GetModuleHandle(winetdll)), ErrorCode,0, @Buffer,SizeOf(Buffer),nil);
  try
    while (Len > 0) and {$IFDEF UNICODE}(CharInSet(Buffer[Len – 1],[#0..#32,
        '.'])) {$ELSE}(Buffer[Len- 1] in [#0..#32, '.']) {$ENDIF} do Dec(Len);
    SetString(Result, Buffer, Len);
  finally
    LocalFree(HLOCAL(Buffer));
  end;
end;

Наш последний пример очень интересен. А как насчет старой винной бутылки (1993 г.) с формами (и виноградом :-)), старинной исторической картины 1619 г., дат, символов и позиционных углов_:

https://my6code.files.wordpress.com/2022/12/wine_1993_20221230_141947.jpg?w=768

И результат убедителен, в том числе и то, что год на изображении этикетки был правильно распознан как 1619:

{“lang”: “it”, “all_text”: “DS\nPODERE CAPACCIA\n1619\nLuggo deffo apacia\nQUERCIAGRANDE\nVino da tavola della Toscana\n1993\nProdotto e imbottigliato all'origin\ nPodere Capaccia\nPacini Giampaolo & C. s.a.s.\nRadda in Chianti (SI) — Italia\nItalia", "аннотации": ["DS", "PODERE", "CAPACCIA", "1619", "Luggo", "deffo" , "apacia", "QUERCIAGRANDE", "Vino", "da", "tavola", "della", "Toscana", "1993", "Prodotto", "e", "imbottigliato", "all'origin" , «Подере», «Капачча», «Пачини», «Джампаоло», «&», «К.», «с.а.с.», «Радда», «ин», «Кьянти», «(», «СИ», «)», «-», «Италия», «Италия»]}

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

Кроме того, доступ к API предоставляется в REST-подобном интерфейсе (Representational State Transfer), предоставляющем ресурсы базы данных или предварительно обученные модели в формате JSON с типом содержимого в заголовке ответа.

Примечание. Если язык программирования не указан в примере кода из живой демонстрации, вы все равно можете выполнять вызовы API с помощью библиотеки HTTP-запросов, написанной на нашем языке программирования, как мы делали с GET или POST.

Вывод:

API Image to Text от APILayer обнаруживает и извлекает текст из изображений, используя современные алгоритмы оптического распознавания символов (OCR) в сочетании с нейронной сетью под названием LSTM. Он может обнаруживать тексты разных размеров, шрифтов и даже почерк или сложные числа.

И еще более удивительным является тот факт, что алгоритм даже видит правильное число, которое мы изо всех сил пытаемся увидеть:

Можете ли вы узнать номер типа от локомотива?

{"lang": "und", "all_text": "E\n15015", "annotations": ["E", "15015"]}
 mX4 executed: 13/01/2023 16:35:41  Runtime: 0:0:2.628  Memload: 42% use

Исходный скрипт: 1176_APILayer_Demo12.txt

Ссылка:

https://apilayer.com/marketplace/image_to_text-api

https://apilayer.com/docs

https://my6.code.blog/2022/09/02/webpostdata/

http://www.kleiner.ch/kleiner/images/uml_buch.jpg

Документ и инструмент: https://maxbox4.wordpress.com

Ссылка на скрипт: 1176_APILayer_Demo1.txt

Appendix: A Delphi REST client API to consume REST services written in any programming language with a class from maXbox4 integration:
https://github.com/fabriciocolombo/delphi-rest-client-api/blob/master/src/HttpConnectionWinInet.pas

API предназначен для работы с Delphi 7 или более поздней версии; в более новых версиях используются общие методы.

https://github.com/fabriciocolombo/delphi-rest-client-api

Макс Клейнер, 01.13.2023

Это была почти такая же работа, как и любая другая, моя работа заключалась в том, чтобы хранить архив технических фотографий для поиска и инвентаризации текстов, особенно чисел и ключевых цифр. Для этого я протестировал программное обеспечение OCR на основе этой нейронной сети.

Реально это DB 103 180–6, SNCF 15013, SBB 11160, SNCB 1801, ÖBB 6010.08 (Базель, 1977 г., оцифровано с фото: SBB).

Программное обеспечение получено в формате JSON: {"lang": "und", "all_text": "DB\n103 180–6\n15013\n11160\nI01\n6010.08", "аннотации": ["DB", "103" , «180–6», «15013», «11160», «I01», «6010.08»]}, была всего одна ошибка I01 вместо 1801!

Затем я протестировал аналогичную конфигурацию с моделью изображения:

API также распознал Hitachi в фоновом режиме: {"lang": "und", "all_text": "DB\n103 193–9\n28\nHITACHI\n15015\nON\n11161\nB\n00 180100\n9\n8010. 07\n9», «аннотации»: [«DB», «103», «193–9», «28», «HITACHI», «15015», «ON», «11161», «B», «00 ", "180100", "9", "8010.07", "9"]}

Забавная вещь снова B 1801: два прожектора между ними распознаются как 00, а швейцарский крест символически распознается как ON!

Тестирование очень маленького текста также включало:

От поезда до самолета, вот что видит детектор изображения: