Как программно распознать QR-код из картинки на сервере 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В современной разработке на платформе 1С часто возникает задача автоматизации обработки входящих данных. Одним из популярных сценариев является получение фотографий через Telegram-ботов. Когда пользователь отправляет фото чека или документа с QR-кодом, сервер 1С должен самостоятельно «прочитать» это изображение и извлечь текстовые данные. Поскольку встроенных средств для декодирования произвольных изображений (непосредственно из файла в текст) в платформе 1С на текущий момент не предусмотрено, нам необходимо рассмотреть использование внешних инструментов и библиотек. Для решения этой задачи можно использовать инструмент для чтения штрихкодов и QR-кодов из изображений и PDF.

В рамках данной статьи мы подробно разберем несколько эффективных способов решения этой задачи: от использования самописных микросервисов на языке Go до интеграции с профессиональными библиотеками компьютерного зрения.

Способ 1. Использование консольной утилиты на языке Go

Проанализируем подход, который заключается в создании небольшой вспомогательной программы на языке Go. Этот язык отлично подходит для таких задач, так как позволяет скомпилировать код в единый исполняемый файл (.exe для Windows или бинарный файл для Linux), который не требует установки дополнительных сред выполнения на сервере.

Рассмотрим код на языке Go, который использует специализированную библиотеку gozxing для декодирования QR-кодов. Проанализируем представленный ниже алгоритм:


package main

import (
	"fmt"
	"image"
	"image/png"
	"io"
	"os"
	"path/filepath"

	"github.com/h2non/filetype"
	"github.com/makiuchi-d/gozxing"
	"github.com/makiuchi-d/gozxing/qrcode"
	"github.com/sunshineplan/imgconv"
	"github.com/sunshineplan/pdf"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func decodeQR(file io.Reader) string {
	img, imgType, err := image.Decode(file)
	check(err)
	bmp, err := gozxing.NewBinaryBitmapFromImage(img)
	check(err)
	qrReader := qrcode.NewQRCodeReader()
	result, err := qrReader.Decode(bmp, nil)
	check(err)
	return result.String()
}

func main() {
	if len(os.Args) < 3 {
		fmt.Println("Использование: qrsсan.exe входной_файл выходной_файл")
		return
	}
	inFile := os.Args[1]
	outFile := os.Args[2]

	file, err := os.Open(inFile)
	check(err)
	defer file.Close()

	// В реальном приложении здесь может быть логика конвертации из разных форматов
	result := decodeQR(file)
	
	f, err := os.Create(outFile)
	check(err)
	f.WriteString(result)
	f.Close()
}

После компиляции этого кода мы получим файл gozxing.exe. Теперь выясним, как вызвать это приложение из кода 1С. Разберем процедуру на сервере, которая сохраняет картинку во временный файл, вызывает нашу утилиту и считывает результат:


&НаСервере
Функция РаспознатьQRИзКартинкиНаСервере(ИмяФайлаКартинки)
    
    ИмяВременногоКаталога = ПолучитьИмяВременногоФайла();
    СоздатьКаталог(ИмяВременногоКаталога);
    
    // Предположим, бинарник хранится в макете обработки как Двоичные Данные
    ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
    ДвоичныеДанныеПриложения = ОбработкаОбъект.ПолучитьМакет("gozxing_exe");
    
    ИмяФайлаПриложения = ИмяВременногоКаталога + "\gozxing.exe";
    ДвоичныеДанныеПриложения.Записать(ИмяФайлаПриложения);
    
    ИмяФайлаРезультата = ПолучитьИмяВременногоФайла("txt");
    
    // Формируем командную строку: приложение.exe путь_к_картинке путь_к_результату
    СтрокаКоманды = СтрШаблон("%1 %2 %3", ИмяФайлаПриложения, ИмяФайлаКартинки, ИмяФайлаРезультата);
    
    // Запускаем приложение и ждем завершения
    ЗапуститьПриложение(СтрокаКоманды, ИмяВременногоКаталога, Истина);
    
    // Считываем то, что распознала утилита
    ТекстРезультат = "";
    ФайлРезультата = Новый Файл(ИмяФайлаРезультата);
    Если ФайлРезультата.Существует() Тогда
        ЧтениеТекста = Новый ЧтениеТекста(ИмяФайлаРезультата, КодировкаТекста.UTF8);
        ТекстРезультат = СокрЛП(ЧтениеТекста.Прочитать());
        ЧтениеТекста.Закрыть();
    КонецЕсли;
    
    // Очистка временных файлов
    Попытка
        УдалитьФайлы(ИмяВременногоКаталога);
        УдалитьФайлы(ИмяФайлаРезультата);
    Исключение
        // Логируем ошибку удаления, если необходимо
    КонецПопытки;
    
    Возврат ТекстРезультат;
    
КонецФункции

Способ 2. Использование библиотеки ZBar

Если ваша серверная ОС — Linux, или вы предпочитаете проверенные open-source инструменты, проанализируем использование ZBar. Это мощный набор инструментов для сканирования штрихкодов.

Рассмотрим последовательность действий для реализации этого метода:

  1. Установка: На сервере Linux выполните команду sudo apt-get install zbar-tools. Для Windows скачайте zbarimg.exe.
  2. Вызов: Используйте аналогичный метод ЗапуститьПриложение. Утилита zbarimg умеет выводить результат прямо в консоль (stdout).
  3. Обработка: Проанализируем команду: zbarimg --raw путь_к_файлу. Флаг --raw позволяет получить только содержимое кода без лишней служебной информации.

Преимущество ZBar заключается в его исключительной скорости и поддержке множества форматов помимо QR (например, EAN-13, Code 128). Также в 1С возможна простая генерация QR и штрихкодов без библиотек.

Способ 3. Скрипты на Python и OpenCV

В случаях, когда пользователи присылают фотографии низкого качества (размытые, под углом, со вспышкой), стандартные библиотеки могут давать сбой. Здесь на помощь приходит Python с библиотекой OpenCV.

Разберем, почему этот метод считается наиболее надежным:

Для интеграции с 1С на сервере должен быть установлен интерпретатор Python. 1С сохраняет файл, вызывает python decode_script.py image.jpg и получает ответ через текстовый файл или консольный вывод.

Способ 4. Внешние компоненты (Native API)

Посмотрим на решение, которое не требует вызова внешних исполняемых файлов. Это использование Внешних компонент 1С. Существуют готовые компоненты, написанные на C++, которые используют движок ZXing (Zebra Crossing).

Проанализируем преимущества этого подхода:

Рекомендации по предварительной обработке изображений

Выясним, почему иногда код не распознается, хотя визуально он виден. Часто проблема кроется в качестве исходного фото. Разберем шаги, которые помогут улучшить результат сканирования:

  1. Контрастность: QR-код — это высококонтрастный объект. Повышение контрастности через внешние утилиты (например, ImageMagick) перед распознаванием может поднять вероятность успеха на 30-40%.
  2. Масштабирование: Слишком большие изображения (современные смартфоны делают фото 12+ Мп) замедляют работу библиотек. Оптимально сжимать картинку или выполнить преобразование PDF в PNG до 1000-1500 пикселей по большой стороне.
  3. Обрезка полей: Лишний фон в кадре может запутать простые алгоритмы поиска. Если известно примерное положение кода, предварительная обрезка будет крайне полезна.

Важное замечание: При работе на сервере всегда следите за правами доступа. Пользователь, от имени которого запущен процесс rphost (обычно это usr1cv8), должен иметь права на исполнение внешних файлов и запись в используемые временные папки. Также не забывайте генерировать уникальные имена для временных файлов, используя ПолучитьИмяВременногоФайла(), чтобы избежать конфликтов при одновременной работе нескольких пользователей.

← На главную