Пишу данный пост с целью поделиться своим проектом, занявшим 10 часов моей жизни на выходных и выполненным с целью понять возможности современных методов анализа данных. Публикация может рассматриваться как пример удачной реализации для людей, несведущих в этой области знания, а также как просьба указать мои ошибки для людей, соответственно, сведущих.
Дано: видео-поток с камеры видеонаблюдения, на котором имеется фрагмент 100x50 пикселей с изображением конкретно парковочного места, на котором может присутствовать или отсутствовать лишь конкретный автомобиль.
Задача: определить наличие или отсутствие автомобиля на парковочном месте.
Получение изображения с камеры
Я использую библиотеку openCV для получения и предобработки изображения.
Следующий код я использовал для построения датасета, который использую для обучения нейросети: я фотографирую ежечасно парковочное место, и после получения 60 фотографий вручную разделяю их на фото с машиной и без неё.
import cv2 as cv
import numpy as np
import time
cap = cv.VideoCapture()
r = 0
while r <=100:
cap.open('http://**.**.***.***:***/*****CG?container=mjpeg&stream=main') #URL-адрес видеопотока
hasFrame, frame = cap.read()#Чтение кадра из потока
frame = frame[100:200, 300:750]
box = [0,335,100,385]
quantframe = frame[box[0]:box[2], box[1]:box[3]]#Сохранение в отдельную переменную части кадра с изображением машины
r+=1
cv.imwrite(str(r)+'.png',quantframe) #Сохранение изображения машины в файл
print('saved')
cap.release()
time.sleep(3600)
key = cv.waitKey(1)
if key & 0xFF == ord('q'):
cv.destroyAllWindows()
break
Обработка изображения
Я посчитал верным решением обучать нейросеть не на исходных изображениях, а на изображениях с контурами автомобиля, найденными посредством функции cv2.findcontours(...).
Вот код, преобразующий исходное изображение в изображение контуров:
def contoursfinder(image):
img = image.copy()
srcimg = img.copy()
hsv_min = np.array((0, 0, 0), np.uint8)
hsv_max = np.array((255, 255, 60), np.uint8) #Поскольку контуры находятся по различиям в цвете между частями картинки, необходимо подобрать параметры, исходя из цветовой гаммы картинки
hsv = cv.cvtColor( img, cv.COLOR_BGR2HSV )
thresh = cv.inRange( hsv, hsv_min, hsv_max )
contours, _ = cv.findContours(thresh, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
img = np.zeros((100,50,3), np.uint8)
cv.drawContours(img, contours, -1, (255,255,255), 1, cv.LINE_AA)
return cv.cvtColor(img, cv.COLOR_BGR2GRAY)
Результат работы функции:
Нейронная сеть
Я использовал библиотеку tensorflow(keras).
Архитектура сети списана с примера с интернетов: для меня неочевидно объяснение, почему именно так. Если знающие люди расскажут или подскажут где почитать, почему эта архитектура эффективна или почему какая-та другая будет эффективнее, буду безмерно благодарен.
Модель нейросети: последовательна, состоит из двух плотных скрытых слоев в 256 и 128 нейронов и входного, выходного слоев.
model = keras.Sequential([
keras.layers.Flatten(input_shape=(100, 50)),
keras.layers.Dense(256, activation=tf.nn.relu),
keras.layers.Dense(128, activation=tf.nn.relu),
keras.layers.Dense(2, activation=tf.nn.softmax)
])
model.compile(optimizer=tf.train.AdamOptimizer(),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(trainingimagesarr, trainingimagesarrlabel, epochs=1, callbacks=[tbCallBack])
Перед обучением вся numpy матрица была поделена на 255, дабы давать на вход нейросети числа в диапазоне от 0 до 1.
trainingimagesarr = trainingimagesarr / 255.0
trainingimagesarrlabel = np.array(trainingimagesarrlabel)-1
Теперь я могу вызвав функцию:
def realtest():
cap = cv.VideoCapture()
cap.open('http://**.**.***.***:***/*****CG?container=mjpeg&stream=main')
hasFrame, frame = cap.read()
frame = frame[100:200, 300:750]
quantframe = frame[0:100,275:325]
quantframe = contoursfinder(quantframe)
return model.predict(np.array([quantframe]))[0][1]>0.60
получить данные о наличии автомобиля на стоянке.
Сильно не пинайте, но чуть-чуть :-)
Спасибо!
Комментарии (8)
unwrecker
18.02.2019 10:13А цель проекта какая? Можно сделать полезное приложение, если находить свободные места на парковке.
mehos
18.02.2019 13:52О, я над похожей задачей работал некоторое время для личных целей. Основная проблема была в том, что автолюбители не брезгуют ставить автомобили не по разметке. Ставят криво, поперек, по диагонали: кто как сумел. И, т.о., задача сводилась к тому, чтобы посчитать расстояние между стоящими автомобилями и определить, хватит ли его для парковки еще одного автомобиля. Я делал без нейросетей, в каком-то виде все работает, но ключевым моментом осталось требование: камера должна быть правильно установлена.
bibiw_one Автор
18.02.2019 23:00У меня задача попроще: парковочное место — личное, машина ставится всегда одинаково, и никто кроме одной машины там не появляется
Вероятно, можно было бы справиться и без нейросети, но целью и лейтмотивом затеи являлось изучение, пусть и поверхностное, возможностей данного метода
arizhiy
18.02.2019 22:50+1> Если знающие люди расскажут или подскажут где почитать, почему эта архитектура эффективна или почему какая-та другая будет эффективнее, буду безмерно благодарен.
Для распознавания изображений лучше использовать свертчные сети (почитай как они работают например VGG, ResNet и тд)
Но вобще непонятные твои результаты, есть ли что улучшать или нет
sshikov
Я мало что понимаю в нейронных сетях, чтобы критиковать само решение. Но мне кажется, что свою домашнюю работу вы не доделали. Ну вот смотрите:
>Я посчитал верным решением обучать нейросеть не на исходных изображениях, а на изображениях с контурами автомобиля, найденными посредством функции cv2.findcontours(...).
Резонно, но: если бы вы довели свою идею до результата, то есть, провели бы обучение двумя способами, и сравнили бы качество распознавания, вы бы реально извлекли что-то полезное из своего эксперимента, и возможно что не только для себя.
Ну или вот тут:
>Архитектура сети списана с примера с интернетов: для меня неочевидно объяснение, почему именно так.
Опять же, домашняя работа не завершена. Нормальный вариант выглядел бы так: архитектура взята вот тут (ссылка), там она применяется для решения похожей задачи (почему вы или автор архитектуры считаете, что они похожи), с хорошими результатами. А так вообще непонятно, что за архитектуру вы взяли, и почему именно ее?
Ну и кстати, ваши-то результаты где? Каково качество, быстродействие, какие-то еще показатели? Оно вообще работает?
bibiw_one Автор
Спасибо за комментарий
Насколько я понимаю, многослойный полносвязный персептрон совершенно не используется для распознавания изображений. Возможно, я бы получил лучшие результаты, использовав бы сверточную архитектуру, которая применяется повсеместно для анализа изображений.
Мой интерес состоит в том числе и в том, насколько просто использовать простые структуры: в нейросети сравнительно мало нейронов(этим объясняется высокое быстродействие), однако она работает с 80% точностью(для кадров разнесенных во времени). Работает это только потому, что я анализирую не сами изображения, а найденные алгоритмом контуры
Подобный подход к решению задачи классификации изображений(персептрон) я увидел в примере из документации tensorflow(они классифицировали MNIST датасет, черно-белые картинки 25х25 пикселей с изображениями разных видов одежды).