INT 21h

Hi, I am Vladimir Smagin, SysAdmin and Kaptain. Telegram Email / GIT / RSS / GPG

Python + FANN или как я написал нейронную сеть для определения свободности ж\д переезда

№ 8212 В разделе Programming от November 5th, 2016,
В подшивках: ,

У нас по городу висят камеры на некоторых ключевых перекрестках и ж\д переездах. Например, переезд на улице Мокрушина. Но это не всегда удобно, т.к. перед выездом приходится смотреть на камеры. Поскольку я модный авторадиоклубень и даже немного программист было принято решение написать программу, которая постит в наш клубный телеграм уведомление когда открываются или закрываются переезды.

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

Итак, я выкачиваю видеопоток длительностью буквально несколько секунд. Этого хватит и на обучение, и на распознавание. Анализировать всю картинку нифига не хорошо. Нужно из нее вырезать только часть и анализировать ее. Я средствами ffmpeg сначала вырезаю нужный мне кусочек из видеофайла размером 28х16 пикселов, а затем потрошу это маленькое видео на отдельные кадры. На картинке внизу наглядно показаны сэмплы, которыми я обучал нейросеть. Захват необходимо делать в разное время суток, т.к. освещение постоянно меняется. Вечером это может быть натриевые лампы, дающие дополнительную красноту, а днем яркость вообще снижается и светофор может быть не виден.

pereezd_obuch

Лепим простейший скрипт, который выкачивает видеофайл, вырезает нужный из него прямоугольник и разрезает на отдельные кадры. Назовем его grab.sh и в параметре ему будем передавать 0 или 1 (нет поезда, есть поезд). Ничего сложного:

#!/bin/bash

HM=$(date +"%H_%M")
echo $HM
stream=$(curl -s http://cdn08.vtomske.ru/hls/stream6.m3u8|grep stream|head -n 1)
echo $stream
curl -s http://cdn08.vtomske.ru/hls/$stream > temp.ts
ffmpeg -loglevel panic -i "temp.ts" -filter:v "crop=28:16:1099:491" "temp_cropped.mp4"
ffmpeg -loglevel panic -i "temp_cropped.mp4" -vf fps=1 "$1/$HM-%d.png"
rm temp.ts temp_cropped.mp4

Итак, сэмплы вырезаны и разложены по каталогам. Теперь необходимо провести обучение сети. Я использовал библиотеки PIL и pyfann. Поскольку я обрабатываю картинки размером 28х16 пикселов у меня получается 448 нейронов, 3 слоя и 1 выходное значение 0 или 1. Я использую только красный канал от картинки. Создаем файл learn.py:

from pyfann import libfann
from PIL import Image
import os

У меня есть 3 массива, куда я помещаю данные для обучения:

datastruct = []
files=[]
learn=[]

files хранит имена файлов, datastruct хранит в себе яркость красного для каждой картинки, а в learn готовые ответы 0 или 1.

Файлы для обучения раскиданы по 2 директориям по аналогии “есть поезд”, “нет поезда”. Делаем поиск по директориям и помещаем найденное в массив:

for filename in os.listdir("0"):
    if filename.endswith(".png"):
        files.append("0/"+filename)
        learn.append([0])

for filename in os.listdir("1"):
    if filename.endswith(".png"):
        files.append("1/"+filename)
        learn.append([1])

Подготовка закончена. Самое время собрать данные в память:

for filename in files:
    im = Image.open(filename, 'r')
    pixel_values = list(im.getdata(0))
    datastruct.append(pixel_values)

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

desired_error = 0.001
max_epochs = 1000
epochs_between_reports = 1000

ann = libfann.neural_net()
ann.create_standard_array((448,150,1))
ann.set_activation_function_hidden(libfann.SIGMOID_SYMMETRIC_STEPWISE)
ann.set_activation_function_output(libfann.SIGMOID_SYMMETRIC_STEPWISE)
train_data = libfann.training_data()
train_data.set_train_data(datastruct, learn)
ann.train_on_data(train_data,max_epochs, epochs_between_reports, desired_error)
ann.save('fann.data')
ann.destroy()

Ура! Ура! Ура! Файл обучения сохранен и теперь можно приступать к распознаванию.

Делаем скрипт, который выкачает видеофайл, порежет и разберет на картинки:

#!/bin/bash

stream=$(curl -s http://cdn08.vtomske.ru/hls/stream6.m3u8|grep stream|head -n 1)
echo $stream
curl -s http://cdn08.vtomske.ru/hls/$stream > temp.ts
ffmpeg -loglevel panic -i "temp.ts" -filter:v "crop=28:16:1099:491" "temp_cropped.mp4"
ffmpeg -loglevel panic -i "temp_cropped.mp4" -vf fps=1 "detect_images/%d.png"
python detect.py
rm temp.ts temp_cropped.mp4 detect_images/*

Ничего сложного. Теперь делаем непосредственно скрипт detect.py:

from pyfann import libfann
from PIL import Image

ann = libfann.neural_net()
ann.create_from_file('fann.data')
imdir="detect_images"
files = ["1.png"]
im = Image.open(imdir+"/"+files[0], 'r')
pix = list(im.getdata(0))
res = ann.run(pix)
print res
if res[0]>0.7:
    print "Train!"
else:
    print "Road clear"

И все! Можно пробовать уже что-нибудь определить. Утренний тест (серое время суток):

root@dev:/opt/detector# ./check.sh
stream6-36738.ts
[1.0]
Train!
root@dev:/opt/detector# ./check.sh
stream6-36740.ts
[1.0]
Train!
root@dev:/opt/detector# ./check.sh
stream6-36811.ts
[0.3132553062939588]
Road clear
root@dev:/opt/detector# ./check.sh
stream6-37074.ts
[0.27650208828934875]
Road clear

Ночной тест

Screenshot_2016-11-05_23-32-51

По результатам видим, что поезд проехал, а потом переезд открылся. Все определено верно.

Скачать готовый код можно в моем репозитории: https://git.blindage.org/21h/pyfann-train-detector

Документации вменяемой для pyfann все еще нет. Вот вам полезная ссылка http://blog.psibi.in/2012/04/using-fann-to-create-networks-properly.html

2 комментариев »

2 responses to “Python + FANN или как я написал нейронную сеть для определения свободности ж\д переезда”

  1. Михаил says:

    А зачем нейросеть? Почему цвет светофора определить без нейросетей?

  2. 21h says:

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

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Облачная платформа
Яндекс.Метрика

Fortune cookie: Sniff sniff... Hey! Who farted?