Pull to refresh

Поддержка камеры и распознавание цифр в браузере «Опера»

Reading time3 min
Views6.4K
Я вчера заморочился на отличненько. Мне показалось скучным и грустным вводить цифры счёта за квартиру в окошко «Госуслуг» и решил сделать автоматическую распознавалку чисел, попутно изучив работу с камерой из браузера.

Распознавалка

Доступ к камере — экспериментальный стандарт, поэтому мало кто из браузеров может им похвастаться, я использовал специальный билд «Opera-Labs-Camera», который можно взять с сайта снапшотов «Оперы». Работать мой пример, соответственно, будет только там, если хотите попробовать, нужно его скачать.

Вообще говоря, аналогичное API есть и в «Хроме», нужно только включить его в конфиге, я поддержку его сделал, но не испытывал.

АПИ оказалось несложным. Всё, что нужно сделать — соединить специальным образом тег VIDEO с источником стримового видео; потом я 10 раз в секунд забираю кадр с видео и кладу в CANVAS (на скриншоте он цветной), оттуда вырезаю небольшую область, перевожу в градации серого, беру за порог 75% от усреднённого цвета и перевожу всё в ч/б.

var vid = document.getElementById('video-stream');

// для ВебКита — переопределяем метод
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;    

if (navigator.getUserMedia) {
    // вообще getUserMedia имеет ещё один параметр — callback, который вызывается, когда
    // произошла ошибка, но я его не использую
    navigator.getUserMedia('video', function (stream) {

        // всё прошло успешно, можно привязать к нашему тегу VIDEO поток
        vid.src = window.webkitURL ?
             window.webkitURL.createObjectURL(stream) :
             stream;
      });
}


Больше всего из трёх часов, которые у меня ушли на это, я делал распознавание цифр. Алгоритмы, которые я нашёл в интернете, были очень монструозными, да и переписывать готовое было скучно, поэтом я перепробовал несколько вариантов, которые пришли мне в голову.

В итоге, лучше всех распознаёт следующий алгоритм.



Сначала я очевидным образом разбиваю изображение на цифры, это совершенно неинтересно, но вкратце опишу. Двигаясь снизу, ищу нижнюю границу по появлению чёрных пикселей, потом продолжаю движение до их исчезновения. То же слева и справа. Потом примерно так же ищу границы цифр, отбрасывая слишком короткие последовательности и прерывая слишком длинные (если на бумаге есть пятна или цифры слиплись).

Так получаются прямоугольники цифр.

Дальнейшее нарисовано на картинке — каждая цифра условно разделяется вертикальной линией по середине. Слева и справа от линии считаю количество переходов к чёрному цвету, двигаясь от центра, строка за строкой. Получаются комбинации из пар чисел.

Например, на картинке слева и справа от линий будет по одному переходу, кроме линии №4, где справа перехода не будет.

Я их прореживаю — одинаковые последовательно идущие заменяю на одно значение. В итоге, запись для «шестёрки» будет выглядеть вот так: 1|1, 1|0, 1|1. Вертикальная черта тут символизирует мою разделительную линию.

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

Например, «0» и «8» дают комбинацию «1|1», но отличаются количеством переходов на средней линии: два и три, соответственно.

Собственно, на верхнем скриншоте в большом текстовом поле как и видно эти комбинации. Первым там записан номер по порядку, потом показатель для средней линии и, через двоеточие, двойки цифр по левой и правой части.

Алгоритм «шумит», из-за того, что дрожит рука с бумагой, из-за освещения. Поэтому я накапливаю статистику и указываю ту цифру, которая в этом позиции распознавалась чаще других. Статистику сбрасываю, если количество объектов на экране изменилось.

Далеко не идеальный алгоритм, но у меня и не было цели сделать продакшн-решение.

Код не привожу, он довольно объёмный, доступен по ссылке.
Tags:
Hubs:
+69
Comments34

Articles

Change theme settings