In [2]:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import cv2
import glob
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import time
from sklearn.svm import LinearSVC
from sklearn.preprocessing import StandardScaler
from skimage.feature import hog
from sklearn.cross_validation import train_test_split
import pickle
from scipy.ndimage.measurements import label
from moviepy.editor import VideoFileClip
In [3]:
# block to loop through vehicle and non-vehicle datasets, append to lists
vehicles_files = glob.glob('dataset/vehicles/**/*.png',recursive=True)
non_vehicles_files = glob.glob('dataset/non-vehicles/**/*.png',recursive=True)
vehicles = []
non_vehicles = []
for i in range(len(vehicles_files)):
vehicles.append(plt.imread(vehicles_files[i]))
for i in range(len(non_vehicles_files)):
non_vehicles.append(plt.imread(non_vehicles_files[i]))
In [4]:
def get_hog_features(img, orient, pix_per_cell, cell_per_block,
vis=False, feature_vec=True):
'''
Purpose: To extract hog features from image
Inputs:
img - image to process
orient - orientations to process hog features for
pix_per_cell - number of pixels to use per cell
cell_per_block - number of cells per block
vis - whether to produce a visualization or not
feature_vec - whether to return a ravelled feature vector or not
Outputs:
[vis] (if vis is True) - a numpy array containing the returned image
feature_vec - the returned hog features
'''
# Call with two outputs if vis==True
if vis == True:
# note that transform_sqrt is set to False
features, hog_image = hog(img, orientations=orient,
pixels_per_cell=(pix_per_cell, pix_per_cell),
cells_per_block=(cell_per_block, cell_per_block),
transform_sqrt=False,
visualise=vis, feature_vector=feature_vec)
return features, hog_image
# Otherwise call with one output
else:
# note that transform_sqrt is set to False
features = hog(img, orientations=orient,
pixels_per_cell=(pix_per_cell, pix_per_cell),
cells_per_block=(cell_per_block, cell_per_block),
transform_sqrt=False,
visualise=vis, feature_vector=feature_vec)
return features
def bin_spatial(img, size=(32, 32)):
'''
Purpose: Compute binned colour features
Inputs:
img - image to have spatial features extracted
size - size to resize input image to
Outputs:
features - ravelled and resized input features
'''
# Use cv2.resize().ravel() to create the feature vector
features = cv2.resize(img, size).ravel()
# Return the feature vector
return features
# Note: NEED TO CHANGE bins_range if reading .png files with mpimg!
def color_hist(img, nbins=32, bins_range=(0, 256)):
'''
Purpose: Compute colour histogram features
Inputs:
img - image to have colour features extracted from (3 channels)
nbins - number of bins to use for histogram
bins_range - colour range for channels
Outputs:
hist_features - colour histogram features of image
'''
# Compute the histogram of the color channels separately
channel1_hist = np.histogram(img[:,:,0], bins=nbins, range=bins_range)
channel2_hist = np.histogram(img[:,:,1], bins=nbins, range=bins_range)
channel3_hist = np.histogram(img[:,:,2], bins=nbins, range=bins_range)
# Concatenate the histograms into a single feature vector
hist_features = np.concatenate((channel1_hist[0], channel2_hist[0], channel3_hist[0]))
# Return the individual histograms, bin_centers and feature vector
return hist_features
def extract_features(imgs, color_space='RGB', spatial_size=(32, 32),
hist_bins=32, orient=9,
pix_per_cell=8, cell_per_block=2, hog_channel=0,
spatial_feat=True, hist_feat=True, hog_feat=True):
'''
Purpose: Extract features from a list of images
Inputs:
imgs - list of images
color_space - colour space to extract features from
spatial_size - image shape to use for spatial parameter extraction
hist_bins - number of histogram bins for colour feature extraction
orient - number of HOG orientations to use
pix_per_cell - number of pixels to use per cell
cell_per_block - number of cells per block
hog_channel - hog channels to use for HOG feature extraction
spatial_feat - whether to include spatial features or not
hist_feat - whether to include colour histogram features or not
hog_feat - whether to use HOG features or not
Outputs:
features - a feature vector with the desired features for the images
'''
# Create a list to append feature vectors to
features = []
# Iterate through the list of images
for image in imgs:
file_features = []
# Read in each one by one
# apply color conversion if other than 'RGB'
if color_space != 'RGB':
if color_space == 'HSV':
feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
elif color_space == 'LUV':
feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2LUV)
elif color_space == 'HLS':
feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2HLS)
elif color_space == 'YUV':
feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2YUV)
elif color_space == 'YCrCb':
feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2YCrCb)
else: feature_image = np.copy(image)
# boolean conditions to determine which features are extracted
if spatial_feat == True:
spatial_features = bin_spatial(feature_image, size=spatial_size)
file_features.append(spatial_features)
if hist_feat == True:
# Apply color_hist()
hist_features = color_hist(feature_image, nbins=hist_bins)
file_features.append(hist_features)
if hog_feat == True:
# Call get_hog_features() with vis=False, feature_vec=True
if hog_channel == 'ALL':
hog_features = []
# loop through each channel of image for feature extraction if 'ALL' was used
for channel in range(feature_image.shape[2]):
hog_features.append(get_hog_features(feature_image[:,:,channel],
orient, pix_per_cell, cell_per_block,
vis=False, feature_vec=True))
hog_features = np.ravel(hog_features)
else:
# otherwise, use specified channel
hog_features = get_hog_features(feature_image[:,:,hog_channel], orient,
pix_per_cell, cell_per_block, vis=False, feature_vec=True)
# Append the new feature vector to the features list
file_features.append(hog_features)
features.append(np.concatenate(file_features))
# Return list of feature vectors
return features
def slide_window(img, x_start_stop=[None, None], y_start_stop=[None, None],
xy_window=(64, 64), xy_overlap=(0.5, 0.5)):
'''
Purpose: determine sliding windows to be searched based on input parameters
Inputs:
img - image to be searched
x_start_stop - start and stop values in x range
y_start_stop - start and stop values in y range
xy_window - window size to be used for window sliding
xy_overlap - x and y overlap fractions to be used for window sliding
Outputs:
window_list - a list of containing windows
'''
# If x and/or y start/stop positions not defined, set to image size
if x_start_stop[0] == None:
x_start_stop[0] = 0
if x_start_stop[1] == None:
x_start_stop[1] = img.shape[1]
if y_start_stop[0] == None:
y_start_stop[0] = 0
if y_start_stop[1] == None:
y_start_stop[1] = img.shape[0]
# Compute the span of the region to be searched
xspan = x_start_stop[1] - x_start_stop[0]
yspan = y_start_stop[1] - y_start_stop[0]
# Compute the number of pixels per step in x/y
nx_pix_per_step = np.int(xy_window[0]*(1 - xy_overlap[0]))
ny_pix_per_step = np.int(xy_window[1]*(1 - xy_overlap[1]))
# Compute the number of windows in x/y
nx_windows = np.int(xspan/nx_pix_per_step) - 1
ny_windows = np.int(yspan/ny_pix_per_step) - 1
# Initialize a list to append window positions to
window_list = []
# Loop through finding x and y window positions
for ys in range(ny_windows):
for xs in range(nx_windows):
# Calculate window position
startx = xs*nx_pix_per_step + x_start_stop[0]
endx = startx + xy_window[0]
starty = ys*ny_pix_per_step + y_start_stop[0]
endy = starty + xy_window[1]
# Append window position to list
window_list.append(((startx, starty), (endx, endy)))
# Return the list of windows
return window_list
# Define a function to draw bounding boxes
def draw_boxes(img, bboxes, color=(0, 0, 255), thick=6):
'''
Purpose: draw bounding boxes on image
Inputs:
img - image to draw boxes onto
bboxes - list of bounding boxes
color - colour to use for drawing boxes
thick - thickness of bounding boxes to be drawn
Outputs:
imcopy - image with bounding boxes drawn
'''
# Make a copy of the image
imcopy = np.copy(img)
# Iterate through the bounding boxes
for bbox in bboxes:
# Draw a rectangle given bbox coordinates
cv2.rectangle(imcopy, bbox[0], bbox[1], color, thick)
# Return the image copy with boxes drawn
return imcopy
# Define a function to extract features from a single image window
# This function is very similar to extract_features()
# just for a single image rather than list of images
def single_img_features(img, color_space='RGB', spatial_size=(32, 32),
hist_bins=32, orient=9,
pix_per_cell=8, cell_per_block=2, hog_channel=0,
spatial_feat=True, hist_feat=True, hog_feat=True):
'''
Purpose: Extract features from a single image
Inputs:
img - image for features to be extracted from
color_space - colour space to extract features from
spatial_size - image shape to use for spatial parameter extraction
hist_bins - number of histogram bins for colour feature extraction
orient - number of HOG orientations to use
pix_per_cell - number of pixels to use per cell
cell_per_block - number of cells per block
hog_channel - hog channels to use for HOG feature extraction
spatial_feat - whether to include spatial features or not
hist_feat - whether to include colour histogram features or not
hog_feat - whether to use HOG features or not
Outputs:
features - a feature vector with the desired features for the image
'''
#1) Define an empty list to receive features
img_features = []
#2) Apply color conversion if other than 'RGB'
if color_space != 'RGB':
if color_space == 'HSV':
feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
elif color_space == 'LUV':
feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2LUV)
elif color_space == 'HLS':
feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
elif color_space == 'YUV':
feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2YUV)
elif color_space == 'YCrCb':
feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2YCrCb)
else: feature_image = np.copy(img)
#3) Compute spatial features if flag is set
if spatial_feat == True:
spatial_features = bin_spatial(feature_image, size=spatial_size)
#4) Append features to list
img_features.append(spatial_features)
#5) Compute histogram features if flag is set
if hist_feat == True:
hist_features = color_hist(feature_image, nbins=hist_bins)
#6) Append features to list
img_features.append(hist_features)
#7) Compute HOG features if flag is set
if hog_feat == True:
if hog_channel == 'ALL':
hog_features = []
for channel in range(feature_image.shape[2]):
hog_features.extend(get_hog_features(feature_image[:,:,channel],
orient, pix_per_cell, cell_per_block,
vis=False, feature_vec=True))
else:
hog_features = get_hog_features(feature_image[:,:,hog_channel], orient,
pix_per_cell, cell_per_block, vis=False, feature_vec=True)
#8) Append features to list
img_features.append(hog_features)
#9) Return concatenated array of features
features = np.concatenate(img_features)
return features
# Define a function you will pass an image
# and the list of windows to be searched (output of slide_windows())
def search_windows(img, windows, clf, scaler, color_space='RGB',
spatial_size=(32, 32), hist_bins=32,
hist_range=(0, 256), orient=9,
pix_per_cell=8, cell_per_block=2,
hog_channel=0, spatial_feat=True,
hist_feat=True, hog_feat=True):
'''
Purpose: search windows of image to predict if they contain a car or not
Inputs:
img - image to search
windows - windows to search within image
clf - classifier to use for predictions
scaler - scaler to use for scaling features
color_space - colour space to extract features from
spatial_size - image shape to use for spatial parameter extraction
hist_bins - number of histogram bins for colour feature extraction
orient - number of HOG orientations to use
pix_per_cell - number of pixels to use per cell
cell_per_block - number of cells per block
hog_channel - hog channels to use for HOG feature extraction
spatial_feat - whether to include spatial features or not
hist_feat - whether to include colour histogram features or not
hog_feat - whether to use HOG features or not
Outputs:
windows containing true predictions
'''
#1) Create an empty list to receive positive detection windows
on_windows = []
#2) Iterate over all windows in the list
for window in windows:
#3) Extract the test window from original image
test_img = cv2.resize(img[window[0][1]:window[1][1], window[0][0]:window[1][0]], (64, 64))
#4) Extract features for that window using single_img_features()
features = single_img_features(test_img, color_space=color_space,
spatial_size=spatial_size, hist_bins=hist_bins,
orient=orient, pix_per_cell=pix_per_cell,
cell_per_block=cell_per_block,
hog_channel=hog_channel, spatial_feat=spatial_feat,
hist_feat=hist_feat, hog_feat=hog_feat)
#5) Scale extracted features to be fed to classifier
test_features = scaler.transform(np.array(features).reshape(1, -1))
#6) Predict using your classifier
prediction = clf.predict(test_features)
#7) If positive (prediction == 1) then save the window
if prediction == 1:
on_windows.append(window)
#8) Return windows for positive detections
return on_windows
def add_heat(heatmap, bbox_list):
'''
Purpose: return incremented heatmap based on bounding boxes
Inputs:
heatmap - heatmap to be incremented
bbox_list - list of bounding boxes
Outputs:
heatmap - incremented heatmap
'''
# Iterate through list of bboxes
for box in bbox_list:
# Add += 1 for all pixels inside each bbox
# Assuming each "box" takes the form ((x1, y1), (x2, y2))
heatmap[box[0][1]:box[1][1], box[0][0]:box[1][0]] += 1
# Return updated heatmap
return heatmap
def apply_threshold(heatmap, threshold):
'''
Purpose: threshold a heatmap based on a certain value to remove false positives
Inputs;
heatmap - input heatmap to be thresholded
threshold - heat value to use for thresholding (integer)
Outputs:
thresholded heat map
'''
# Zero out pixels below the threshold
heatmap[heatmap <= threshold] = 0
# Return thresholded map
return heatmap
def draw_labeled_bboxes(img, labels):
'''
Purpose: draw labeled bounding boxes based on given labels
Inputs:
image to have bounding boxes drawn onto
labels: bounding box labels for each car
Outputs:
image with bounding boxes appended to
'''
# Iterate through all detected cars
copy_img = np.copy(img)
bboxes = []
for car_number in range(1, labels[1]+1):
# Find pixels with each car_number label value
nonzero = (labels[0] == car_number).nonzero()
# Identify x and y values of those pixels
nonzeroy = np.array(nonzero[0])
nonzerox = np.array(nonzero[1])
# Define a bounding box based on min/max x and y
bbox = ((np.min(nonzerox), np.min(nonzeroy)), (np.max(nonzerox), np.max(nonzeroy)))
bboxes.append(bbox)
# Draw the box on the image, value of 255 squared since image is divided by 255
# to be scaled between 0 and 1
cv2.rectangle(copy_img, bbox[0], bbox[1], (0,0,255**2), 6)
# Return the image
return copy_img
def draw_labeled_bboxes_video(img, labels):
'''
Purpose:
Draw labeled bounding boxes based on given labels. This is the same as draw_labeled_bboxes
except that it also returns the bounding boxes
Inputs:
image to have bounding boxes drawn onto
labels: bounding box labels for each car
Outputs:
copy_img - image with bounding boxes appended to
bboxes - bounding boxes
'''
# Iterate through all detected cars
copy_img = np.copy(img)
bboxes = []
for car_number in range(1, labels[1]+1):
# Find pixels with each car_number label value
nonzero = (labels[0] == car_number).nonzero()
# Identify x and y values of those pixels
nonzeroy = np.array(nonzero[0])
nonzerox = np.array(nonzero[1])
# Define a bounding box based on min/max x and y
bbox = ((np.min(nonzerox), np.min(nonzeroy)), (np.max(nonzerox), np.max(nonzeroy)))
bboxes.append(bbox)
# Draw the box on the image
cv2.rectangle(copy_img, bbox[0], bbox[1], (0,0,255**2), 6)
# Return the image
return copy_img, bboxes
def draw_old_bboxes(img, bboxes):
'''
Purpose: draw a given list of bounding boxes on an image
Inputs:
img - image to have bounding boxes drawn onto
bboxes - list of bounding boxes
Outputs:
copy_img - image with bounding boxes appended
'''
# copy input image
copy_img = np.copy(img)
# loop through all bounding boxes and append rectangle to image
for i in range(len(bboxes)):
cv2.rectangle(copy_img, bboxes[i][0],bboxes[i][1], (0,0,255**2), 6)
return copy_img
In [5]:
# function to train classifier
def train_classifier(cars,notcars,color_space,orient, pix_per_cell, cell_per_block, hog_channel, spatial_size,
hist_bins, spatial_feat, hist_feat, hog_feat):
'''
Purpose: This function is used to train a linear SVM classifier on the car and not car dataset
Inputs:
cars - list of car data
notcars - list of not-car data
color_space - colour space to extract features from
spatial_size - image shape to use for spatial parameter extraction
hist_bins - number of histogram bins for colour feature extraction
orient - number of HOG orientations to use
pix_per_cell - number of pixels to use per cell
cell_per_block - number of cells per block
hog_channel - hog channels to use for HOG feature extraction
spatial_feat - whether to include spatial features or not
hist_feat - whether to include colour histogram features or not
hog_feat - whether to use HOG features or not
Outputs:
svc - the fitted support vector machine classifier
X_scaler - the input feature scaler
'''
# extract car and non-car features
car_features = extract_features(cars, color_space=color_space,
spatial_size=spatial_size, hist_bins=hist_bins,
orient=orient, pix_per_cell=pix_per_cell,
cell_per_block=cell_per_block,
hog_channel=hog_channel, spatial_feat=spatial_feat,
hist_feat=hist_feat, hog_feat=hog_feat)
notcar_features = extract_features(notcars, color_space=color_space,
spatial_size=spatial_size, hist_bins=hist_bins,
orient=orient, pix_per_cell=pix_per_cell,
cell_per_block=cell_per_block,
hog_channel=hog_channel, spatial_feat=spatial_feat,
hist_feat=hist_feat, hog_feat=hog_feat)
# combine features
X = np.vstack((car_features, notcar_features)).astype(np.float64)
# Fit a per-column scaler
X_scaler = StandardScaler().fit(X)
# Apply the scaler to X
scaled_X = X_scaler.transform(X)
# Define the labels vector
y = np.hstack((np.ones(len(car_features)), np.zeros(len(notcar_features))))
# Split up data into randomized training and test sets
rand_state = np.random.randint(0, 100)
X_train, X_test, y_train, y_test = train_test_split(
scaled_X, y, test_size=0.2, random_state=rand_state)
print('Using:',orient,'orientations',pix_per_cell,
'pixels per cell and', cell_per_block,'cells per block')
print('Feature vector length:', len(X_train[0]))
# Use a linear SVC
svc = LinearSVC()
# Check the training time for the SVC
t=time.time()
svc.fit(X_train, y_train)
t2 = time.time()
print(round(t2-t, 2), 'Seconds to train SVC...')
# Check the score of the SVC
print('Test Accuracy of SVC = ', round(svc.score(X_test, y_test), 4))
# Check the prediction time for a single sample
t=time.time()
return svc, X_scaler
In [6]:
# Block to extract hog features and train an SVM classifier
# Read in cars and notcars
cars = vehicles
notcars = non_vehicles
# parameters to pass to functions
color_space = 'YUV' # Can be RGB, HSV, LUV, HLS, YUV, YCrCb
orient = 6 # HOG orientations
pix_per_cell = 8 # HOG pixels per cell
cell_per_block = 2 # HOG cells per block
hog_channel = "ALL" # Can be 0, 1, 2, or "ALL"
spatial_size = (16, 16) # Spatial binning dimensions
hist_bins = 16 # Number of histogram bins
spatial_feat = True # Spatial features on or off
hist_feat = True # Histogram features on or off
hog_feat = True # HOG features on or off
# perform classifier training
this_svc, X_scaler = train_classifier(cars,notcars,color_space,orient, pix_per_cell, cell_per_block, hog_channel, spatial_size,
hist_bins, spatial_feat, hist_feat, hog_feat)
In [7]:
def image_pipeline(img):
'''
Purpose:
Pipeline to process an image and produce an image with detected vehicles drawn by
bounding boxes.
Inputs:
img - image to be processed
Outputs:
draw_img - image with bounding boxes appended
labels - labels corresponding to the drawn bounding boxes
'''
# Min and max in y to search in slide_window() for lower and bottom window search
y_start_stop_bottom = [500, None]
y_start_stop_top = [400, 600]
# Min and max in x to search in slide_window(
x_start_stop = [700,None]
# scale pixel values to be between 0 and 1
image = img.astype(np.float32)/255
# determine sliding windows to be evaluated by classifier
# two sizes of windows are used. Larger ones are used for near-range and
# smaller ones are used for longer-range
windows = slide_window(image, x_start_stop=x_start_stop, y_start_stop=y_start_stop_bottom,
xy_window=(128, 128), xy_overlap=(0.9,0))
windows += slide_window(image, x_start_stop=x_start_stop, y_start_stop=y_start_stop_top,
xy_window=(96, 96), xy_overlap=(0.9,0))
# determine windows that test positively in the image given the passed classifier
hot_windows = search_windows(image, windows, this_svc, X_scaler, color_space=color_space,
spatial_size=spatial_size, hist_bins=hist_bins,
orient=orient, pix_per_cell=pix_per_cell,
cell_per_block=cell_per_block,
hog_channel=hog_channel, spatial_feat=spatial_feat,
hist_feat=hist_feat, hog_feat=hog_feat)
# heat image template of zeros
heat = np.zeros_like(image[:,:,0]).astype(np.float)
# Add heat to each box in box list
heat = add_heat(heat,hot_windows)
# Apply threshold to help remove false positives
heat = apply_threshold(heat,2)
# Visualize the heatmap when displaying
heatmap = np.clip(heat, 0, 255)
# Find final boxes from heatmap using label function
labels = label(heatmap)
# create a copy of image to return
draw_img = np.copy(image)
# append bounding boxes to image copy
draw_img = draw_labeled_bboxes(draw_img, labels)
return draw_img,labels
In [8]:
def video_pipeline(img):
'''
Purpose:
Pipeline to process a video image frame and produce an image with detected vehicles drawn by
bounding boxes. Similar to image_pipeline, but with logic based on frame count
Inputs:
img - image to be processed
Outputs:
draw_img - image with bounding boxes appended
'''
# global variables for count of the frame and the previous list of bounding boxes
global frame_counter
global last_bboxes
# Min and max in y to search in slide_window() for lower and bottom window search
y_start_stop_bottom = [500, None]
y_start_stop_top = [400, 600]
# Min and max in x to search in slide_window(
x_start_stop = [700,None]
# scale pixel values to be between 0 and 1
image = img.astype(np.float32)/255
# create a copy of image to return
draw_img = np.copy(img)
# if no previous bounding boxes or five frames have passed, find new bounding boxes
if frame_counter == 0 or not last_bboxes:
# determine sliding windows to be evaluated by classifier
windows = slide_window(image, x_start_stop=x_start_stop, y_start_stop=y_start_stop_bottom,
xy_window=(128, 128), xy_overlap=(0.9,0.2))
windows += slide_window(image, x_start_stop=x_start_stop, y_start_stop=y_start_stop_top,
xy_window=(96, 96), xy_overlap=(0.9,0.2))
# determine windows that test positively in the image given the passed classifier
hot_windows = search_windows(image, windows, this_svc, X_scaler, color_space=color_space,
spatial_size=spatial_size, hist_bins=hist_bins,
orient=orient, pix_per_cell=pix_per_cell,
cell_per_block=cell_per_block,
hog_channel=hog_channel, spatial_feat=spatial_feat,
hist_feat=hist_feat, hog_feat=hog_feat)
# heat image template of zeros
heat = np.zeros_like(image[:,:,0]).astype(np.float)
# Add heat to each box in box list
heat = add_heat(heat,hot_windows)
# Apply threshold to help remove false positives
heat = apply_threshold(heat,2)
# Visualize the heatmap when displaying
heatmap = np.clip(heat, 0, 255)
# Find final boxes from heatmap using label function
labels = label(heatmap)
# append new bounding boxes
draw_img,last_bboxes = draw_labeled_bboxes_video(draw_img, labels)
# reset counter if five frames have passed, otherwise increment counter
if frame_counter != 4:
frame_counter += 1
else:
frame_counter = 0
# if not drawing new bounding boxes, used previous frame's
elif frame_counter == 4:
frame_counter = 0
draw_img = draw_old_bboxes(draw_img, last_bboxes)
else:
frame_counter += 1
draw_img = draw_old_bboxes(draw_img, last_bboxes)
return draw_img
In [13]:
# block to test image pipeline
%matplotlib inline
'''
fig = plt.figure(figsize=(10,10))
plt.subplot(3,1,1)
test = plt.imread('test_images/test2.jpg')
test_out,lbs = image_pipeline(test)
plt.imshow(test_out)
plt.subplot(3,1,2)
test = plt.imread('test_images/test5.jpg')
test_out,lbs = image_pipeline(test)
plt.imshow(test_out)
plt.subplot(3,1,3)
'''
test = plt.imread('test_images/test6.jpg')
test_out,lbs = image_pipeline(test)
plt.imshow(test_out)
Out[13]:
In [ ]:
# block to test video pipeline
frame_counter = 0
last_bboxes = []
project_output = "project_video_out.mp4"
clip1 = VideoFileClip("project_video.mp4")
out_clip = clip1.fl_image(video_pipeline)
%time out_clip.write_videofile(project_output, audio=False)
In [28]:
# block to demonstrate vehicle and non-vehicle example images
%matplotlib inline
fig = plt.figure(figsize=(10,10))
plt.subplot(1,2,1)
img = vehicles[8]
plt.imshow(img)
plt.title('Vehicle Example Image')
plt.subplot(1,2,2)
img = non_vehicles[10]
plt.imshow(img)
plt.title('Non-Vehicle Example Image')
Out[28]:
In [67]:
# block to demonstrate HOG feature extraction
fig = plt.figure(figsize=(15,15))
plt.subplot(3,4,1)
img = vehicles[8]
img2 = non_vehicles[10]
plt.imshow(img)
plt.title('Car (Original)')
feature_image = cv2.cvtColor(img, cv2.COLOR_RGB2YUV)
_, hog_image = get_hog_features(feature_image[:,:,0], orient=9, pix_per_cell=8, cell_per_block=2,
vis=True, feature_vec=False)
plt.subplot(3,4,2)
plt.title('Car CH-1 HOG')
plt.imshow(hog_image,cmap='gray')
plt.subplot(3,4,3)
plt.title('Non-Car (Original)')
plt.imshow(img2)
plt.subplot(3,4,4)
plt.title('Non-Car CH-1 HOG')
feature_image2 = cv2.cvtColor(img2, cv2.COLOR_RGB2YUV)
_, hog_image2 = get_hog_features(feature_image2[:,:,0], orient=9, pix_per_cell=8, cell_per_block=2,
vis=True, feature_vec=False)
plt.imshow(hog_image2,cmap='gray')
plt.subplot(3,4,5)
plt.title('Car CH-1')
plt.imshow(feature_image[:,:,0],cmap='gray')
plt.subplot(3,4,6)
plt.title('Non-Car CH-1')
plt.imshow(feature_image2[:,:,0],cmap='gray')
plt.subplot(3,4,7)
plt.title('Car CH-2')
plt.imshow(feature_image[:,:,1],cmap='gray')
plt.subplot(3,4,8)
plt.title('Non-Car CH-2')
plt.imshow(feature_image2[:,:,1],cmap='gray')
plt.subplot(3,4,9)
plt.title('Car CH-3')
plt.imshow(feature_image[:,:,2],cmap='gray')
plt.subplot(3,4,10)
plt.title('Non-Car CH-3')
plt.imshow(feature_image2[:,:,2],cmap='gray')
Out[67]:
In [80]:
# block to demonstrate sliding windows
y_start_stop_bottom = [500, None] # Min and max in y to search in slide_window()
y_start_stop_top = [400, 600]
x_start_stop = [700,None] # Min and max in x to search in slide_window()
image = mpimg.imread('test_images/test2.jpg')
draw_image = np.copy(image)
fig = plt.figure(figsize=(10,10))
image = image.astype(np.float32)/255
windows = slide_window(image, x_start_stop=x_start_stop, y_start_stop=y_start_stop_bottom,
xy_window=(128, 128), xy_overlap=(0.9,0.2))
windows += slide_window(image, x_start_stop=x_start_stop, y_start_stop=y_start_stop_top,
xy_window=(96, 96), xy_overlap=(0.9,0.2))
for i, window in enumerate(windows):
if i % 4 == 0:
cv2.rectangle(draw_image, window[0], window[1],(0,0,255), 6)
plt.imshow(draw_image)
Out[80]:
In [87]:
# demonstration of adding bounding boxes without thresholding
y_start_stop_bottom = [500, None] # Min and max in y to search in slide_window()
y_start_stop_top = [400, 600]
x_start_stop = [700,None] # Min and max in x to search in slide_window()
image = mpimg.imread('test_images/test6.jpg')
draw_image = np.copy(image)
image = image.astype(np.float32)/255
windows = slide_window(image, x_start_stop=x_start_stop, y_start_stop=y_start_stop_bottom,
xy_window=(128, 128), xy_overlap=(0.9,0.2))
windows += slide_window(image, x_start_stop=x_start_stop, y_start_stop=y_start_stop_top,
xy_window=(96, 96), xy_overlap=(0.9,0.2))
hot_windows = search_windows(image, windows, this_svc, X_scaler, color_space=color_space,
spatial_size=spatial_size, hist_bins=hist_bins,
orient=orient, pix_per_cell=pix_per_cell,
cell_per_block=cell_per_block,
hog_channel=hog_channel, spatial_feat=spatial_feat,
hist_feat=hist_feat, hog_feat=hog_feat)
window_img = draw_boxes(draw_image, hot_windows, color=(0, 0, 255), thick=6)
fig = plt.figure(figsize=(15,15))
plt.subplot(1,2,1)
plt.title('Original Image')
plt.imshow(draw_image)
plt.subplot(1,2,2)
plt.imshow(window_img)
plt.title('Windowed Image')
Out[87]:
In [88]:
# demonstration of heat map
# Read in a pickle file with bboxes saved
# Each item in the "all_bboxes" list will contain a
# list of boxes for one of the images shown above
#box_list = pickle.load( open( "bbox_pickle.p", "rb" ))
# Read in image similar to one shown above
#image = mpimg.imread('test_image.jpg')
heat = np.zeros_like(image[:,:,0]).astype(np.float)
# Add heat to each box in box list
heat = add_heat(heat,hot_windows)
# Apply threshold to help remove false positives
heat = apply_threshold(heat,2)
# Visualize the heatmap when displaying
heatmap = np.clip(heat, 0, 255)
fig = plt.figure(figsize=(15,15))
plt.subplot(121)
plt.imshow(window_img)
plt.title('Car Positions')
plt.subplot(122)
plt.imshow(heatmap, cmap='hot')
plt.title('Heat Map')
fig.tight_layout()