重磅干貨,,第一時間送達
在本文中,使用Python編程語言和庫Keras和OpenCV建立CNN模型,,成功地對交通標志分類器進行分類,,準確率達96%。開發(fā)了一款交通標志識別應(yīng)用程序,該應(yīng)用程序具有圖片識別和網(wǎng)絡(luò)攝像頭實時識別兩種工作方式,。 本文的GitHub:https://github.com/Daulettulegenov/TSR_CNN 提供一個開源的交通標志的數(shù)據(jù)集,,希望能夠幫助到各位小伙伴:http://www.nlpr./pal/trafficdata/recognition.html 近年來,計算機視覺是現(xiàn)代技術(shù)發(fā)展的一個方向,。這個方向的主要任務(wù)是對照片或攝像機中的物體進行分類,。在通常的問題中,使用基于案例的機器學(xué)習(xí)方法來解決,。本文介紹了利用機器學(xué)習(xí)算法進行計算機視覺在交通標志識別中的應(yīng)用,。路標是一種外形固定的扁平人造物體。道路標志識別算法應(yīng)用于兩個實際問題,。第一個任務(wù)是控制自動駕駛汽車,。無人駕駛車輛控制系統(tǒng)的一個關(guān)鍵組成部分是物體識別。識別的對象主要是行人,、其他車輛,、交通燈和路標。第二個使用交通標志識別的任務(wù)是基于安裝在汽車上的DVRs的數(shù)據(jù)自動繪制地圖,。接下來將詳細介紹如果搭建能夠識別交通標志的CNN網(wǎng)絡(luò),。 導(dǎo)入必要的庫 # 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
加載數(shù)據(jù) Python Pandas包幫助我們處理數(shù)據(jù)集。我們首先將訓(xùn)練和測試數(shù)據(jù)集獲取到Pandas DataFrames中,。我們還將這些數(shù)據(jù)集組合起來,,在兩個數(shù)據(jù)集上一起運行某些操作。 # Importing of the Imagescount = 0images = []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 +=1print(" ")images = np.array(images)classNo = np.array(classNo) 為了對已實現(xiàn)的系統(tǒng)進行適當?shù)挠?xùn)練和評估,,我們將數(shù)據(jù)集分為3組,。數(shù)據(jù)集分割:20%測試集,20%驗證數(shù)據(jù)集,,剩余的數(shù)據(jù)用作訓(xùn)練數(shù)據(jù)集,。 # Split DataX_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) 該數(shù)據(jù)集包含34799張圖像,由43種類型的路標組成,。這些包括基本的道路標志,如限速,、停車標志,、讓路、優(yōu)先道路,、“禁止進入”,、“行人”等。 # DISPLAY SOME SAMPLES IMAGES OF ALL THE CLASSESnum_of_samples = []cols = 5num_classes = noOfClassesfig, 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 CATEGORYprint(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() 數(shù)據(jù)集中的類之間存在顯著的不平衡,。有些類的圖像少于200張,,而其他類的圖像超過1000張。這意味著我們的模型可能偏向于過度代表的類別,特別是當它對自己的預(yù)測不自信時,。為了解決這個問題,,我們使用了現(xiàn)有的圖像轉(zhuǎn)換技術(shù)。 為了更好的分類,,數(shù)據(jù)集中的所有圖像都被轉(zhuǎn)換為灰度圖像 # 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)))
數(shù)據(jù)增強是對原始數(shù)據(jù)集進行增強的一種方法,。數(shù)據(jù)越多,結(jié)果越高,,這是機器學(xué)習(xí)的基本規(guī)律,。 #AUGMENTATAION OF IMAGES: TO MAKEIT MORE GENERICdataGen= 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) # DEGREESdataGen.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 CALLEDX_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庫創(chuàng)建一個神經(jīng)網(wǎng)絡(luò)。下面是創(chuàng)建模型結(jié)構(gòu)的代碼: 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 # TRAINmodel = 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的最大拉層,。還添加了系數(shù)為0.25和0.5的Dropout層,,以便網(wǎng)絡(luò)不會再訓(xùn)練。在最后幾行中,,我們添加了一個稠密的稠密層,,該層使用softmax激活函數(shù)在43個類中執(zhí)行分類。 在最后一個epoch結(jié)束時,,我們得到以下值:loss = 0.0523;準確度= 0.9832;Val_loss = 0.0200;Val_accuracy = 0.9943,,這個結(jié)果看起來非常好。之后繪制我們的訓(xùn)練過程 #PLOTplt.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))
我們在測試數(shù)據(jù)集中測試了構(gòu)建的模型,,得到了96%的準確性,。 使用內(nèi)置函數(shù)model_name.save(),我們可以保存一個模型以供以后使用,。該功能將模型保存在本地的.p文件中,,這樣我們就不必一遍又一遍地重新訓(xùn)練模型而浪費大量的時間。 model.save("CNN_model_3.h5") 接下來給大家看一些識別的結(jié)果
|