Traffic Sign Classification with Keras and Deep Learning
Traffic Sign Classification with Keras and Deep Learning
Traffic sign recognition consists of object detection:
- detection/localization Detect and localize where in an input image/frame a traffic sign is.
- classification Take the localized ROI and actually recognize and classify the traffic sign.
The dataset we’ll be using to train our own custom traffic sign classifier is the German Traffic Sign Recognition Benchmark (GTSRB).
Notice how the traffic signs have been pre-cropped for us, implying that the dataset annotators/creators have manually labeled the signs in the images and extracted the traffic sign Region of Interest (ROI) for us.
Recognizing Traffic Signs with CNNs
Data Summary and Exploration
Data Size and Shape
- Size of training set: 34,799 (67%)
- Size of the validation set: 4,410 (9%)
- Size of test set: 12,630 (24%)
- Shape of a traffic sign image: (32, 32, 3)
- Number of unique classes/labels: 43
Data Visualization
Determine what types of preprocessing operations should be applied to the data (if any).
- Inspect a sample of images Check: color channels
- Check the labels Is the label method correct for classification?
- How balanced is the dataset? Are there certain classes that dominate? Are there others that are under-represented?
Data Preprocessing
Contrast enhancement
Use Scikit histogram equalization function,
from tqdm import tqdm from skimage import color, data, exposure def normalize(image_data): '''Contrast Limited Adaptive Histogram Equalization (CLAHE). In addition to regular normalization, this function provides local contrast enhancement -- i.e., details of the image can be enhanced even in regions that are darker or lighter than most of the image. http://scikit-image.org/docs/dev/api/skimage.exposure.html#skimage.exposure.equalize_adapthist ''' norm = np.array([exposure.equalize_adapthist(image, clip_limit=0.1) for image in tqdm(image_data)]) return norm
Augmentation
- Increase the total number of images
- Create an equal distribution of images
- Apply affine transformations.
- Apply ZCA whitening to accentuate edges
Model Architecture
Steps
cd ~/anaconda3 jupyter notebook
Step 0: Load The Data
The GTSRB dataset is pre-split into training/testing splits for us.
Let’s go ahead and define a function to load our data from disk:
from skimage import exposure def load_split(basePath, csvPath): # initialize the list of data and labels data = [] labels = [] # load the contents of the CSV file, remove the first line (since # it contains the CSV header), and shuffle the rows (otherwise # all examples of a particular class will be in sequential order) rows = open(csvPath).read().strip().split("\n")[1:] random.shuffle(rows) # loop over the rows of the CSV file for (i, row) in enumerate(rows): # check to see if we should show a status update if i > 0 and i % 1000 == 0: print("[INFO] processed {} total images".format(i)) # split the row into components and then grab the class ID # and image path (label, imagePath) = row.strip().split(",")[-2:] # derive the full path to the image file and load it imagePath = os.path.sep.join([basePath, imagePath]) image = io.imread(imagePath) # resize the image to be 32x32 pixels, ignoring aspect ratio, # and then perform Contrast Limited Adaptive Histogram # Equalization (CLAHE) image = transform.resize(image, (32, 32)) image = exposure.equalize_adapthist(image, clip_limit=0.1) # update the list of data and labels, respectively data.append(image) labels.append(int(label)) # convert the data and labels to NumPy arrays data = np.array(data) labels = np.array(labels) # return a tuple of the data and labels return (data, labels)load_split() loads each training split respectively. It accepts a path to the base of the dataset as well as a .csv file path which contains the class label for each image.
You can dump the first 3 rows
print(rows[:3])The format of the data is:
Width, Height, X1, Y1, X2, Y2, ClassID, Image PathThe image contrast can be improved by applying an algorithm called Contrast Limited Adaptive Histogram Equalization (CLAHE), the implementation of which can be found in the scikit-image library.
Original images input images can be seen on the left — notice how contrast is very low and some signs cannot be recognize. By applying CLAHE we can improve image contrast.
skimage.exposure.equalize_adapthist(image, kernel_size=None, clip_limit=0.01, nbins=256):
- image(M, N[, C]) ndarray. Input image.
- kernel_size integer or list-like, optional. Defines the shape of contextual regions used in the algorithm. If iterable is passed, it must have the same number of elements as image.ndim (without color channel). If integer, it is broadcasted to each image dimension. By default, kernel_size is 1/8 of image height by 1/8 of its width.
- clip_limit float, optional. Clipping limit, normalized between 0 and 1 (higher values give more contrast).
- nbinsint optional. Number of gray bins for histogram (“data range”).
Now let’s go ahead and load + preprocess our data:
datasetPath = "/home/jerry/datasets/gtsrb" # derive the path to the training and testing CSV files trainPath = os.path.sep.join([datasetPath, "Train.csv"]) testPath = os.path.sep.join([datasetPath, "Test.csv"]) # load the training and testing data print("[INFO] loading training and testing data...") (trainX, trainY) = load_split(datasetPath, trainPath) (testX, testY) = load_split(datasetPath, testPath) # scale data to the range of [0, 1] trainX = trainX.astype("float32") / 255.0 testX = testX.astype("float32") / 255.0 # one-hot encode the training and testing labels numLabels = len(np.unique(trainY)) trainY = to_categorical(trainY, numLabels) testY = to_categorical(testY, numLabels) # account for skew in the labeled data classTotals = trainY.sum(axis=0) classWeight = classTotals.max() / classTotals
留言