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

Дорожные знаки являются неотъемлемой частью нашей повседневной жизни. Они содержат критически важную информацию, которая обеспечивает безопасность всех людей вокруг нас. Дорожный знак представляет собой плоский искусственный объект с фиксированным внешним видом. Существуют две прикладные задачи, в которых используются алгоритмы распознавания дорожных знаков. Первая задача — управлять автономным транспортным средством. Беспилотные автомобили — это автомобили, которые могут передвигаться по дорогам без водителя. Ключевым компонентом системы управления беспилотным транспортным средством является распознавание объектов. Объектами интереса являются в первую очередь пешеходы, другие транспортные средства, светофоры и дорожные знаки. Вторая задача, использующая распознавание дорожных знаков, — это автоматическое сопоставление на основе данных с видеорегистраторов, установленных на автомобилях. Задача актуальна, так как в настоящее время составление и ведение подробных дорожных карт требует либо значительных финансовых затрат, либо большого количества человеческого времени.

Базовые концепты

Компьютерное зрение и классификация изображений

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

Сверточная нейронная сеть (CNN) — основной инструмент для классификации объектов, лиц на фотографиях, распознавания речи. Сверточная нейронная сеть с помощью специальной операции — собственно свертки — позволяет одновременно уменьшить объем хранимой в памяти информации. Трансформация происходит в каждом слое, причем в каждом слое по-разному, как «ребра», «грани» и т. д., далее используются понятия «текстура», «части объектов». В результате такого исследования можно на заключительном этапе правильно классифицировать картинку или выбрать нужный объект на изображении. Сверточные нейронные сети используются достаточно широко и в различных областях. Самым тривиальным вопросом, который можно осветить с помощью нейросетей, стала классификация изображений. В настоящее время CNN и ее модификации считаются ведущими расчетами для поиска объектов в пределах сцены с точки зрения точности. С 2012 года нейронные системы впервые приняли участие в известном во всем мире конкурсе изображений ImageNet. Сверточные сети — это золотая середина между естественно мыслимыми системами и обычным многослойным персептроном. На сегодняшний день лучшие достижения в области фотографии получают с их помощью. В норме точность распознавания таких сетей превышает обычные модели искусственного интеллекта на 10–15%. CNN — это основная технология глубокого обучения.

Библиотеки

# data analysis and wrangling
import numpy as np
import pandas as pd
import os
import random

# visualization
import matplotlib.pyplot as plt
from PIL import Image
# machine learning
from keras.models import Sequential
from keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from keras.utils.np_utils import to_categorical
from keras.layers import Dropout, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
import cv2
from sklearn.model_selection import train_test_split
from keras.preprocessing.image import ImageDataGenerator

Получить данные

Пакеты Python Pandas помогают нам работать с нашими наборами данных. Мы начнем с получения наборов данных для обучения и тестирования в Pandas DataFrames. Мы также объединяем эти наборы данных для одновременного выполнения определенных операций с обоими наборами данных.

# Importing of the Images
count = 0
images = []
classNo = []
myList = os.listdir(path)
print("Total Classes Detected:",len(myList))
noOfClasses=len(myList)
print("Importing Classes.....")
for x in range (0,len(myList)):
    myPicList = os.listdir(path+"/"+str(count))
    for y in myPicList:
        curImg = cv2.imread(path+"/"+str(count)+"/"+y)
        curImg = cv2.resize(curImg, (30, 30))
        images.append(curImg)
        classNo.append(count)
    print(count, end =" ")
    count +=1
print(" ")
images = np.array(images)
classNo = np.array(classNo)

Для правильного обучения и оценки внедренных систем мы разделили набор данных на 3 набора. Разделение набора данных: 20% тестового набора, 20% набора данных проверки, а остальное для обучения набора данных.

# Split Data
X_train, X_test, y_train, y_test = train_test_split(images, classNo, test_size=testRatio)
X_train, X_validation, y_train, y_validation = train_test_split(X_train, y_train, test_size=validationRatio)

Набор данных содержит 34799 изображений и состоит из 43 типов дорожных знаков. К ним относятся основные дорожные знаки, такие как ограничение скорости, знак «стоп», «уступи дорогу», «главная дорога», «въезд запрещен», «пешеходы» и другие.

# DISPLAY SOME SAMPLES IMAGES OF ALL THE CLASSES
num_of_samples = []
cols = 5
num_classes = noOfClasses
fig, axs = plt.subplots(nrows=num_classes, ncols=cols, figsize=(5, 300))
fig.tight_layout()
for i in range(cols):
    for j,row in data.iterrows():
        x_selected = X_train[y_train == j]
        axs[j][i].imshow(x_selected[random.randint(0, len(x_selected)- 1), :, :], cmap=plt.get_cmap("gray"))
        axs[j][i].axis("off")
        if i == 2:
            axs[j][i].set_title(str(j)+ "-"+row["Name"])
            num_of_samples.append(len(x_selected))

# DISPLAY A BAR CHART SHOWING NO OF SAMPLES FOR EACH CATEGORY
print(num_of_samples)
plt.figure(figsize=(12, 4))
plt.bar(range(0, num_classes), num_of_samples)
plt.title("Distribution of the training dataset")
plt.xlabel("Class number")
plt.ylabel("Number of images")
plt.show()

Существует значительный дисбаланс между классами в наборе данных. Некоторые классы имеют менее 200 изображений, в то время как другие имеют более 1000. Это означает, что наша модель может быть смещена в сторону перепредставленных классов, особенно когда она не уверена в своих прогнозах. Чтобы решить эту проблему, мы использовали существующие методы преобразования изображений.

Для лучшей классификации все изображения из набора данных были преобразованы в изображения в градациях серого. Оттенки серого — цветовой режим изображений, отображаемых в оттенках серого, помещенных в виде таблицы в качестве эталонов яркости белого цвета.

# PREPROCESSING THE IMAGES
def grayscale(img):
    img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    return img

def equalize(img):
    img =cv2.equalizeHist(img)
    return img

def preprocessing(img):
    img = grayscale(img)     # CONVERT TO GRAYSCALE
    img = equalize(img)      # STANDARDIZE THE LIGHTING IN AN IMAGE
    img = img/255            # TO NORMALIZE VALUES BETWEEN 0 AND 1 INSTEAD OF 0 TO 255
    return img

X_train=np.array(list(map(preprocessing,X_train)))  # TO IRETATE AND PREPROCESS ALL IMAGES
X_validation=np.array(list(map(preprocessing,X_validation)))
X_test=np.array(list(map(preprocessing,X_test)))

Увеличение данных — это метод увеличения исходного набора данных. Чем больше данных, тем выше результат, это основное правило машинного обучения.

#AUGMENTATAION OF IMAGES: TO MAKEIT MORE GENERIC
dataGen= ImageDataGenerator(width_shift_range=0.1,   # 0.1 = 10%     IF MORE THAN 1 E.G 10 THEN IT REFFERS TO NO. OF  PIXELS EG 10 PIXELS
                            height_shift_range=0.1,
                            zoom_range=0.2,  # 0.2 MEANS CAN GO FROM 0.8 TO 1.2
                            shear_range=0.1,  # MAGNITUDE OF SHEAR ANGLE
                            rotation_range=10)  # DEGREES
dataGen.fit(X_train)
batches= dataGen.flow(X_train,y_train,batch_size=20)  # REQUESTING DATA GENRATOR TO GENERATE IMAGES  BATCH SIZE = NO. OF IMAGES CREAED EACH TIME ITS CALLED
X_batch,y_batch = next(batches)

Горячее кодирование использовалось для наших категориальных значений y_train, y_test, y_validation.

y_train = to_categorical(y_train,noOfClasses)
y_validation = to_categorical(y_validation,noOfClasses)
y_test = to_categorical(y_test,noOfClasses)

Для создания нейронной сети будет использоваться библиотека Keras. Вот код для создания структуры модели:

def myModel():
    model = Sequential()
    model.add(Conv2D(filters=32, kernel_size=(5,5), activation='relu', input_shape=X_train.shape[1:]))
    model.add(Conv2D(filters=32, kernel_size=(5,5), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(rate=0.25))
    model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
    model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(rate=0.25))
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(rate=0.5))
    model.add(Dense(43, activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model
# TRAIN
model = myModel()
print(model.summary())

history = model.fit(X_train, y_train, batch_size=batch_size_val, epochs=epochs_val, validation_data=(X_validation,y_validation))

В приведенном выше коде использовалось 6 сверточных слоев и 1 полносвязный слой. Сначала в модель были добавлены сверточные слои с 32 фильтрами. Далее мы добавляем сверточный слой с 64 фильтрами. За каждым слоем добавляется максимально вытягивающий слой с размером окна 2×2. Также добавлены слои Dropout с коэффициентами 0,25 и 0,5, чтобы сеть не переобучалась. В последних строках мы добавляем плотный слой Dense, который выполняет классификацию среди 43 классов, используя функцию активации softmax.

По завершении последней эпохи мы получили следующие значения: потеря = 0,0523; точность = 0,9832; val_loss = 0,0200; val_accuracy = 0,9943, что очень хорошо.

#PLOT
plt.figure(1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.legend(['training','validation'])
plt.title('loss')
plt.xlabel('epoch')
plt.figure(2)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.legend(['training','validation'])
plt.title('Acurracy')
plt.xlabel('epoch')
plt.show()
score =model.evaluate(X_test,y_test,verbose=0)
print('Test Score:',score[0])
print('Test Accuracy:',score[1])

#testing accuracy on test dataset
from sklearn.metrics import accuracy_score

y_test = pd.read_csv('Test.csv')
labels = y_test["ClassId"].values
imgs = y_test["Path"].values
data=[]
for img in imgs:
    image = Image.open(img)
    image = image.resize((30,30))
    data.append(np.array(image))
X_test=np.array(data)
X_test=np.array(list(map(preprocessing,X_test)))
predict_x=model.predict(X_test) 
pred=np.argmax(predict_x,axis=1)
print(accuracy_score(labels, pred))

Мы проверили построенную модель на тестовом наборе данных и получили точность 96 процентов.

Используя встроенную функцию model_name.save(), мы можем сохранить модель для последующего использования. Эта функция сохраняет модель в локальном файле .p, поэтому вам не нужно перезапускать модель снова и снова, не теряя при этом много времени.

model.save("CNN_model_3.h5")

Полученные результаты:

В ходе диссертации модель CNN была построена с использованием языка программирования Python и библиотек Keras и OpenCV и успешно классифицировала классификатор дорожных знаков с точностью 96%. Разработано приложение для распознавания дорожных знаков, имеющее 2 варианта работы, распознавание по картинке и распознавание дорожных знаков в режиме реального времени с помощью веб-камеры.

Ссылка на Github: https://github.com/Daulettulegenov/TSR_CNN