Автоматическое распознавание автомобильных номеров на Raspberry Pi
Рассказываем, как самостоятельно создать компактную систему автоматического распознавания номеров автомобилей на одной плате Raspberri Pi с библиотекой OpenALPR.
Рассмотрим задачу создания собственной системы автоматического детектирования и распознавания автомобильных номеров на основе открытой библиотеки OpenALPR. Такие системы применяются не только в карательных целях, чтобы штрафовать водителей, превышающих разрешенную скорость. Так, установленная на контрольном пункте система распознавания сокращает время ожидания водителей перед шлагбаумом и снижает нагрузку постового. Программа сверяет распознанный номер с базой, разрешая или запрещая въезд транспорта. Другое применение – оптимизация городского или локального трафика через трекинг передвижения автомобилей и общественного транспорта по камерам наружного наблюдения. Мы будем рады, если вы поделитесь своими идеями применения таких систем в комментариях.
Что мы хотим сделать?
Итак, когда в кадре видеонаблюдения оказывается автомобиль, система должна обнаружить знак и распознавать его в виде строки, состоящей из набора символов. Нахождение объектов в видеопотоке – задача из области компьютерного зрения. При беглом поиске в интернете можно найти множество публикаций, посвященных распознаванию номеров, но... чаще всего на одном единственном примере. Такие решения, конечно, не универсальны. Автомобильные номера в поле зрения камеры оказываются под разными углами, в меняющихся условиях освещения, могут иметь загрязнения и повреждения. Кроме того, в кадре может одновременно находиться несколько автомобилей.
Универсальные системы требуют обучения на сотнях тысяч предварительно распознанных примеров. Для этого, кроме предообработки изображений, используется глубокое обучение на основе нейросетей. Процесс их тренировки требует наличия мощных видеокарт или распределенных вычислительных систем. В то же время результат в виде предобученной нейросети для распознавания символов вполне может работать и на одноплатных компьютерах, например, Raspberry Pi. Это снижает издержки внедрения и использования технологии.
Таким образом, кроме самой платы, понадобятся следующие инструменты:
- Библиотека для предобработки изображений OpenCV.
- Библиотека распознавания текста Tesseract OCR.
- Библиотека OpenALPR, учитывающая предполагаемый объект распознавания (табличку автомобильного номера) и использующая методы вышеуказанных библиотек.
OpenALPR – это библиотека для автоматического распознавания табличек с буквенно-численными символами, написанная на C++ с интерфейсом для Node.js, Python, Java, Go и C#. Под аббревиатурой OpenALPR скрывается Automatic License Plate Recognition (автоматическое распознавание автомобильных номеров). Пакет предоставляет как открытую библиотеку для разработки собственных приложений, так и платный агент (при желании использовать готовое решение). Библиотека работает как со статичными изображениями, так и с видеопотоком. Документация проекта.
Ниже мы подробно рассмотрим установку OpenALPR на примере Raspberry Pi третьей модели с учетом нюансов. Обратите внимание: при установке важно учитывать зависимости и конкретные версии библиотек.
1. Выполняем update и upgrade ОС
По умолчанию мы предполагаем, что на плате стоит наиболее популярная операционная система для рассматриваемой платы – Raspbian. Все шаги выполняются на правах администратора (root). Начать нужно с двух стандартных команд, обновляющих операционную систему:
apt-get update apt-get upgrade
2. Устанавливаем необходимые пакеты
Перед установкой OpenALPR необходимо разобраться со всеми необходимыми зависимостями:
apt-get install autoconf automake libtool apt-get install libleptonica-dev apt-get install libicu-dev libpango1.0-dev libcairo2-dev apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev apt-get install python-dev python-numpy libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev apt-get install virtualenvwrapper apt-get install liblog4cplus-dev apt-get install libcurl4-openssl-dev
То же можно выполнить в виде однострочной команды:
apt-get install autoconf automake libtool libleptonica-dev libicu-dev libpango1.0-dev libcairo2-dev cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev python-dev python-numpy libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev virtualenvwrapper liblog4cplus-dev libcurl4-openssl-dev
В случае, если apt-get install
для какого-либо из пакетов закончится неудачей (no package found), необходимо вручную найти отсутствующий пакет, используя apt-cache search
.
Tesseract использует библиотеку leptonica версии 1.71, поэтому предварительно ее установим:
cd /usr/src wget http://www.leptonica.org/source/leptonica-1.71.tar.gz tar xf leptonica-1.71.tar.gz cd /usr/src/leptonica-1.71 ./configure make make install
3. Устанавливаем основные библиотеки нужных версий
Как было сказано выше, в основе OpenALPR лежат две библиотеки:
- Tesseract OCR v3.0.4 (важно: OpenALPR не использует Tesseract последней версии)
- OpenCV v2.4.8+
Чтобы предупредить возможные трудности, опишем процесс установки подробнее.
3.1. Tesseract OCR
Скачиваем (клонируем) пакет с git:
cd /usr/src/ git clone https://github.com/tesseract-ocr/tesseract cd /usr/src/tesseract git tag git checkout 3.04.01 ./autogen.sh
Если все прошло успешно, вы получите сообщение:
All done. To build the software now, do something like: $ ./configure [--enable-debug] [...other options]
На следующем шаге нужно настроить библиотеку, как предложено в сообщении выше, то есть запустить ./configure
. Запустим с опцией отладки.
./configure --enable-debug
После того как мы настроили библиотеку, запустим компиляцию:
make -j2
На Raspberry процесс занимает много времени. Поэтому запускаем команду с опцией j2
(в два потока). В случае если это вызовет проблемы, запускайте команду make
без дополнительных параметров. Устанавливаем скомпилированное:
make install
Проверяем результат компиляции:
root@raspberrypi:/usr/local/src/tesseract# tesseract tesseract: error while loading shared libraries: libtesseract.so.3: cannot open shared object file: No such file or directory
Если вы получили схожую ошибку (на этом или следующих этапах) запустите ldconfig
. Вновь проверим результат, теперь всё работает:
root@openalpr-tst01:/usr/src/tesseract# tesseract -v tesseract 3.04.01 leptonica-1.71 libjpeg 6b : libpng 1.2.50 : libtiff 4.0.3 : zlib 1.2.8
Видим номер версии, библиотека установлена.
3.2. OpenCV
Загрузим OpenCV. Разархивируем zip-файл. При этом будет создана директория /usr/src/opencv-2.4.13
.
cd /usr/src wget https://github.com/opencv/opencv/archive/2.4.13.zip unzip 2.4.13.zip
Далее создаем внутри каталог release
, переходим в него и настраиваем проект.
cd opencv-2.4.13 mkdir release cd release cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
Если всё закончится хорошо, мы получим следующее сообщение:
-- Configuring done -- Generating done -- Build files have been written to: /usr/local/src/opencv-2.4.13/release
Если вы получите ошибку вида libdc1394 error: Failed to initialize libdc1394
, запустите следующий код:
ln /dev/null /dev/raw1394 apt-get install libdc1394-22-dev apt-get install libdc1394-22 libdc1394-utils
Далее нужно скомпилировать результат, лучше, как и прежде, с параметром j2
, чтобы сократить время компиляции. То есть в окне терминала это будет выглядеть примерно так:
root@raspberrypi:/usr/src/opencv-2.4.13/release# make -j2
В первый раз процесс может закончиться следующей ошибкой:
[ 47%] Building CXX object modules/ocl/CMakeFiles/opencv_ocl.dir/src/cl_runtime/clamdfft_runtime.cpp.o c++: internal compiler error: Segmentation fault (program cc1plus) Please submit a full bug report, with preprocessed source if appropriate. See <file:///usr/share/doc/gcc-4.9/README.Bugs> for instructions. modules/ocl/CMakeFiles/opencv_ocl.dir/build.make:719: recipe for target 'modules/ocl/CMakeFiles/opencv_ocl.dir/src/cl_runtime/clamdfft_runtime.cpp.o' failed make[2]: *** [modules/ocl/CMakeFiles/opencv_ocl.dir/src/cl_runtime/clamdfft_runtime.cpp.o] Error 4 CMakeFiles/Makefile2:4734: recipe for target 'modules/ocl/CMakeFiles/opencv_ocl.dir/all' failed make[1]: *** [modules/ocl/CMakeFiles/opencv_ocl.dir/all] Error 2 make[1]: *** Waiting for unfinished jobs....
Это может быть вызвано нехваткой памяти. Срабатывает следующий набор действий:
- Перезагрузить плату
- Увеличить файл подкачки (swap)
- Запустить
make clean
и вновьmake
Чтобы увеличить файл подкачки, выполняем следующую последовательность:
fallocate --length 2GiB /root/2G.swap chmod 0600 /root/2G.swap mkswap /root/2G.swap swapon /root/2G.swap
После того как удастся успешно скомпилировать OpenCV, производим установку:
make install
4. Устанавливаем OpenALPR
Наконец, мы можем установить саму OpenALPR. Клонируем репозиторий и проверяем версию:
cd /usr/src git clone https://github.com/openalpr/openalpr.git cd openalpr/src git describe --tags
Например, в нашем случае ответом на последний запрос было v2.1.0-513-gcd2aab0
, то есть версия 2.1.0. Если вы хотите использовать ту же версию, что в нашем примере, используйте git checkout v2.1.0
.
mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_INSTALL_SYSCONFDIR:PATH=/etc .. make make install
Если после запуска make
выводится ошибка, аналогичная случаю с установкой OpenCV, выполняем вышеописанную последовательность действий для OpenCV. Если обнаруживаются ошибки, связанные с отсутствием библиотек:
apt-get install cmake apt-get install liblog4cplus-dev libcurl3-dev sudo apt-get install beanstalkd apt-get install openjdk-7-jdk export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64/
Протестируем полученный результат:
wget http://plates.openalpr.com/h786poj.jpg -O lp.jpg alpr lp.jpg plate0: 8 results - 786P0 confidence: 90.1703 - 786PO confidence: 85.579 - 786PQ confidence: 85.3442 - 786PD confidence: 84.4616 - 7B6P0 confidence: 69.4531 - 7B6PO confidence: 64.8618 - 7B6PQ confidence: 64.627 - 7B6PD confidence: 63.7444
Всё работает. Слева — распознанный номер, справа — вероятность его соответствия реальному номеру на изображении.
Чтобы настроить связку библиотеки с С/С++Java, C#, Java или Python, ознакомьтесь с соответствующим разделом официальной документации. Например, использов связку с Python, вы можете построить систему из нескольких веб-камер, взаимодействующих с общим сервером, обращаясь к отдельным камерам только в случае нестандартных ситуаций, когда номер оказался не распознан.