Здравствуйте, я школьник 11 классов, интересуюсь программированием, около-IT тематикой.
Пишу данный пост с целью поделиться своим проектом, занявшим 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
получить данные о наличии автомобиля на стоянке.
Сильно не пинайте, но чуть-чуть :-)
Спасибо!
Автор: Андрей Крюков