<jupyter_start><jupyter_text>COMP9517 Usama Sadiq Project z5235652<jupyter_code>import cv2 as cv

import numpy as np

import matplotlib.pyplot as plt

from skimage.feature import hog

import os

from sklearn.preprocessing import StandardScaler

from sklearn.svm import LinearSVC

import time

from sklearn.model_selection import train_test_split

from scipy.ndimage.measurements import label<jupyter_output><empty_output><jupyter_text>*** Step 1 - First we will build the car list by reading the imgs from the "Data\positive_imgs" - After this, we will build the not car list by reading the imgs from the "Data\negative_imgs"<jupyter_code>#Load the car and not car data from folders

cars_list = []

not_cars_list = []
#checking the current working dir
print(os.getcwd())
#positive car images extracted using the annotations file
cars_dir = "Data\\positive_imgs\\"

#negative car images extracted using the superannotation software and annotation file
not_car_dir = "Data\\negative_imgs\\"

#No of cars images read
cars_length = len(os.listdir(cars_dir))

#No of not cars images read
not_cars_length = len(os.listdir(not_car_dir))

print("Total no of positive cars: {}".format(cars_length))

print("Total no of negative cars: {}".format(not_cars_length))
    
#print(cars_dir+os.listdir(cars_dir)[100])

#build the cars images list
for i in range(cars_length):

    img = cv.imread(cars_dir+os.listdir(cars_dir)[i])
    
    cars_list.append(img)
    
    #plt.imshow(img)
    
    #plt.show()
print(" Shape of the car images is : h = {}, w = {}, c = {}".format(len(cars_list[0]), len(cars_list[0][0]), len(cars_list[0][0][0])))
#build the not cars images list

for i in range(not_cars_length):
    
    img = cv.imread(not_car_dir+os.listdir(not_car_dir)[i])
    
    not_cars_list.append(img)
print(" Shape of the car images is : h = {}, w = {}, c = {}".format(len(not_cars_list[0]), len(not_cars_list[0][0]), len(not_cars_list[0][0][0])))
#Plot one of the car and not car images just to make sure everything is ok

fig = plt.figure(figsize=(10,10))

plt.subplot(2,2,1)

plt.imshow(cars_list[0])

plt.title("Car")

plt.subplot(2,2,2)

plt.imshow(not_cars_list[3])

plt.title("Not Car")

plt.show()<jupyter_output><empty_output><jupyter_text>***  Step 2 Calculate the HOG Features of all the positive and negative imgs<jupyter_code># func to calculate the hog feature of the img
# return the features and hog img

def hog_features(img, orient, pixels_per_cell, cells_per_block, show_img = False, show_feature_vec = True):
    
    #if we also want to show the hog img along with hog features
    if show_img == True:
        
        features, hog_img = hog(img, orientations = orient, pixels_per_cell = (pixels_per_cell, pixels_per_cell), cells_per_block = (cells_per_block, cells_per_block), transform_sqrt = False, visualize = show_img)
        
        return features, hog_img
        
    else:
        
        features = hog(img, orientations = orient, pixels_per_cell = (pixels_per_cell, pixels_per_cell), cells_per_block=(cells_per_block, cells_per_block), transform_sqrt = False, visualize = show_img)
        
        return features<jupyter_output><empty_output><jupyter_text>Visualize the HOG Features Different values for orientations, pixel_per_cell, cells_per_block were tried but the best results were achieved using the following values<jupyter_code>#getting the best results on the following parameters for the hog

#visualize these results

orient = 9

pixels_per_cell = 16

cells_per_block = 1

feature_img = cars_list[0]

features,img = hog_features(feature_img, orient, pixels_per_cell, cells_per_block, show_img=True, show_feature_vec = True)

# orient = 9

# pixels_per_cell = 8

# cells_per_block = 2

# features_1,img_1 = hog_features(feature_img, orient, pixels_per_cell, cells_per_block, show_img=True, show_feature_vec = True)

plt.figure(figsize=(10,10))

plt.subplot(121)

plt.imshow(img)

# plt.subplot(122)

# plt.imshow(img_1)

plt.show()
print("No of Hog Features: {}".format(len(features)))<jupyter_output>No of Hog Features: 81<jupyter_text>Extract the Hog features I tired 2 methods 1) I calculated the hog features of all the channels combined but that didnt give me good results 2) Extract the hog features of a single channel and then combine them which gave me better results<jupyter_code>#func to extract all the hog features

def extract_hog_features(imgs, orient = 9, pixels_per_cell = 16, cells_per_block = 1):
    
    #build a list of the hog features for all the images
    features = []
    
    #Looping through the images
    for i in imgs:
        
        #Using the YCrCb as it gave me the best results
        #Convert the img to YCrCb
        feature_image = cv.cvtColor(i, cv.COLOR_BGR2YCrCb)
        
        #Hog features of the image. Extracted separatly and then combined
        hog_features_L = []
        
        for channel in range(feature_image.shape[2]):
            
            hog_features_L.append(hog_features(feature_image[:,:,channel],
                                     orient, pixels_per_cell, cells_per_block, show_img=False, show_feature_vec=True))
        
        
        #shape of Hog_Features_L C * Hog Features of the Color channel
        # 3 * 81
        
        #Convert the hog features to 1 D array
        hog_features_L = np.ravel(hog_features_L)
        
        #print(hog_features_L.shape)
        
        #features_hog = hog_features(feature_img, orient, pix_per_cell, cell_per_block, visual_img=False, feature_vec = True)
        
        #Append the hog features of the image 
        features.append(hog_features_L)
        
        
    
    return features<jupyter_output><empty_output><jupyter_text>Hog features of all the car images<jupyter_code>#Calculate the HOG Features of all the cars images
car_features= extract_hog_features(cars_list, orient=orient, pixels_per_cell=pixels_per_cell, cells_per_block=cells_per_block)
print("Shape of the car features {} * {}. which is no of images * hog_features".format(len(car_features), len(car_features[0])))<jupyter_output>Shape of the car features 1442 * 243. which is no of images * hog_features<jupyter_text>Hog features of all the non car images<jupyter_code>#Calculate the HOG Features of all the not car images
not_car_features = extract_hog_features(not_cars_list, orient=orient, pixels_per_cell=pixels_per_cell, cells_per_block=cells_per_block)
print("Shape of the not car features {} * {}. which is no of images * hog_features".format(len(not_car_features), len(not_car_features[0])))<jupyter_output>Shape of the not car features 1014 * 243. which is no of images * hog_features<jupyter_text>Step 3 Create the input matrix (X) for the svm model<jupyter_code>#Creating X which will be the inputs for our model.

#shape will be (No of images of car features and not car feature stacked together) * (Hog features of images of car and not car features)

x = np.concatenate((car_features,not_car_features), axis=0).astype(np.float64)
print("Shape of Xtrain = {} which is (no of cars and not cars images) * (hog fearures of images)".format(x.shape))<jupyter_output>Shape of Xtrain = (2456, 243) which is (no of cars and not cars images) * (hog fearures of images)<jupyter_text>Normalize the Input matrix using the StandardScaler<jupyter_code>#Normalize the data so that mean is zero and variance is 1

#Declare the Scaler which will normalize the data
X_Scaler = StandardScaler().fit(x)

#Normalize the data
scaled_X = X_Scaler.transform(x)
print("Shape of scaled_X = {} which is (no of cars and not cars images) * (hog fearures of images)".format(scaled_X.shape))<jupyter_output>Shape of scaled_X = (2456, 243) which is (no of cars and not cars images) * (hog fearures of images)<jupyter_text>Create the output matrix (y) of the model<jupyter_code>#Build the Targets/outputs for our model
y = np.concatenate((np.ones(len(car_features)), np.zeros(len(not_car_features))))
print("Shape of Y = {} which is (no of cars and not cars images) * 1".format(y.shape))
#y = np.hstack((np.ones(len(car_features_1)), np.zeros(len(not_car_features))))
#print(y_1)<jupyter_output><empty_output><jupyter_text>Split the DataSet into train/test data sets<jupyter_code>#split the X and Y between train and test data 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("Shape of X_train = {} no of images * hog_features".format(X_train.shape))
print("Shape of X_test = {} no of images * hog_features".format(X_test.shape))
print("Shape of Y_train = {} no of images * 1".format(y_train.shape))
print("Shape of Y_test = {} no of images * 1".format(y_test.shape))<jupyter_output>Shape of X_train = (1964, 243) no of images * hog_features
Shape of X_test = (492, 243) no of images * hog_features
Shape of Y_train = (1964,) no of images * 1
Shape of Y_test = (492,) no of images * 1<jupyter_text>Declare the svm model<jupyter_code>#Declare the SVC model
svc = LinearSVC()

svc.fit(X_train, y_train)

print('Test Accuracy : {}'.format(round(svc.score(X_test, y_test), 4)))<jupyter_output>Test Accuracy : 0.9736<jupyter_text>Evaluate the model<jupyter_code>#read an image to test the SVC model and detect the car

#print(os.getcwd())

path_dir = "Data\\benchmark_velocity_train\\clips\\1\\imgs\\040.jpg"

img = cv.imread(path_dir)

plt.imshow(img)

plt.show()
#Convert the color for the image to RGB and later we will convert it to YCrCb
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
#Helper func to draw bounding box on img using the windows found for cars

def draw_bounding_box(img, windows_found, color=(255,0,0), thickness=6):
    
    for bounding_box in windows_found:
        
        cv.rectangle(img, bounding_box[0], bounding_box[1], color, thickness)
        
    return img<jupyter_output><empty_output><jupyter_text>Implementing sliding window We will implement sliding window as we want to slide a window over the image and using our classifier predict if it is a car or not and using that we can make a bounding box<jupyter_code>def sliding_window(img, xlim, ylim, xy_WindowSize, xy_Overlap):
    
    #print(img.shape, xlim, ylim, xy_Window_Size, xy_Overlap)
    
    #Declare the default values for xlim and ylim if no values given
    
    if xlim == [None, None]:
        
        xlim[0] = 0
        xlim[1] = img.shape[1]
        
        #print(xlim)
    
    if ylim == [None, None]:
        
        ylim[0] = 0
        ylim[1] = img.shape[0]
    
    #print(xlim[1], xlim[0])
    
    #print(ylim[1], ylim[0])
    
    #Now we have to calculate the area/region which we want to be searched
    deltaX = xlim[1] - xlim[0]
    deltaY = ylim[1] - ylim[0]
    
    #print(deltaX,deltaY)
    
#   #print(xy_Overlap)
    
    #Now we have to compute the number of pixels in X axis
    no_of_pixels_per_step_x = np.int(xy_WindowSize[0] * (1 - xy_Overlap[0]))
    
    #Now we have to calculate the number of pixels in y axis
    no_of_pixels_per_step_y = np.int(xy_WindowSize[1] * (1 - xy_Overlap[1]))
    
    #print(no_of_pixels_per_step_x, no_of_pixels_per_step_y)
    
    #Now we will calculate the number of windows for X axis
    no_of_windows_x = np.int( (deltaX - ( np.int(xy_WindowSize[0] * (xy_Overlap[0] ))) ) / no_of_pixels_per_step_x)
    
    #Now we will calculate the number of windows for y axis
    no_of_windows_y = np.int( (deltaY - ( np.int(xy_WindowSize[1] * (xy_Overlap[1] ))) ) / no_of_pixels_per_step_y )
    
    #print(no_of_windows_x, no_of_windows_y)
    
    #list for appending the windows coordinates
    window_List = []
    
    for y in range(no_of_windows_y):
        
        for x in range(no_of_windows_x):
            
            #starting coord for x
            start_X = x * no_of_pixels_per_step_x + xlim[0]
            
            #ending coord for x
            end_X = start_X + xy_WindowSize[0]
            
            #starting coord for y
            start_Y = y * no_of_pixels_per_step_y + ylim[0]
                             
            #ending coord for y
            end_Y = start_Y + xy_WindowSize[1]
            
            window_List.append(((start_X, start_Y), (end_X, end_Y)))

    return window_List<jupyter_output><empty_output><jupyter_text>Visualizing the sliding window<jupyter_code>image = cv.imread("Data\\benchmark_velocity_train\\clips\\1\\imgs\\040.jpg")
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)

xy_window = [(64,64), (96,96), (128,128), (256,256)]
y_lim = [[300, 600], [300, 600], [300, 600], [300, 600]]

windows_temp = []
for i in range(len(xy_window)):
    windows = sliding_window(image, [None, None], y_lim[i], 
                        xy_window[i], (0.5, 0.5))
    #print(len(windows))
    windows_temp.append(windows) 

#Flatten windows_temp
windows_final = sum(windows_temp, [])

print("Windows Final",len(windows_final))
window_img = draw_bounding_box(image, windows_final, color=(0, 0, 255), thickness=6)   

plt.imshow(window_img)

plt.show()
# func to search for cars using our classifier in each windows found by sliding windows and if found then append it to a list
def search_window_for_cars(img, windows_found_1, classifier, X_Scalar, orient, pixels_per_cell, cells_per_block):
    
    #store car windows
    car_found_windows = []
    
    #traverse all the images
    #extract the img of size 60,60
    #classify it
    #and if it is a car include it in the list
    
    for window_1 in windows_found_1:
        
        #setting the dim
        dim = (60,60)
        
        #setting the x_start for the window
        x_start = window_1[0][1]
        
        #setting the x_end for the window
        x_end = window_1[1][1]
        
        #setting the y_start for the window
        y_start = window_1[0][0]
        
        #setting the y_stop for the window
        y_end = window_1[1][0]
        
        #plt.imshow(img)
        
        #plt.show()
        
        #extracting the window from the original img and resizing it to 60 * 60
        img_2 = cv.resize(img[x_start:x_end, y_start:y_end ], dim)
        
        #print(img.shape)
        
        #find the hog features for the extracted img
        img_hog_features = extract_hog_features([img_2], orient=orient, pixels_per_cell=pixels_per_cell, cells_per_block=cells_per_block)
        
        #Scale the extracted features
        Scaled_img_hog_features = X_Scalar.transform(np.array(img_hog_features).reshape(1,-1))
        
        #make prediction using the classifier and the scaled hog features
        pred = classifier.predict(Scaled_img_hog_features)
        
        #if a car is found, append it to the list
        if pred == 1:
            car_found_windows.append(window_1)
        
    return car_found_windows<jupyter_output><empty_output><jupyter_text>Use the heatmap approach to reduce the false positive bounding boxes<jupyter_code>#func for drawing the bodunding boxes after labeling the img using heatmap
def draw_bounding_boxes_labels(img, labels):
    
    #loop through all the detected cars and draw bounding boxes for them
    
    no_of_cars_detected = labels[1] + 1
    
    for car in range(1, no_of_cars_detected):
        
        #Find all the pixel values using the car label and car value
        # and make sure they are nonzero
        
        non_zero_pixels = (labels[0] == car).nonzero()
        
        #Find the x coords of these non zero pixel.
        non_zero_pixels_X = np.array(non_zero_pixels[1])
        
        #Find the y coords of these non zero pixel.
        non_zero_pixels_Y = np.array(non_zero_pixels[0])
        
        #we will define the bounding box on the basis of the min and max values of x and y. As this will help us to decrease our false postives
        bounding_box = ((np.min(non_zero_pixels_X), np.min(non_zero_pixels_Y)), (np.max(non_zero_pixels_X), np.max(non_zero_pixels_Y)))
        
        cv.rectangle(img, bounding_box[0], bounding_box[1], (0,0,255), 6)
        
        return img


#func to generate a heat map image of the image so that we can highlight only the pixels which are pixels of the detected cars
def add_heat_to_bounding_box_pixels(heat_map, bounding_box_list):
    
    #loop through the list of bounding box and add 1 for all the pixels inside the bounding boxes
    
    for bounding_box in bounding_box_list:
        
        #We assume that each bounding boxes are of the form ((x1, y1), (x2,y2))
        
        x1 = bounding_box[0][1]
        
        y1 = bounding_box[1][1]
        
        x2 = bounding_box[0][0]
        
        y2 = bounding_box[1][0]
        
        heat_map[x1 : y1, x2 : y2] += 1
    
    return heat_map
    
#func to apply a threshold so that can we reduce our false positives in our images    
def apply_heatmap_threshold(heat_map, threshold):
    
    heat_map[heat_map <= threshold] = 0
    
    return heat_map<jupyter_output><empty_output><jupyter_text>Main Method<jupyter_code>#Input paths to the image files
Input_Img_files = ['Data\\benchmark_velocity_train\\clips\\1\\imgs\\040.jpg']

#Loop through all the input image files

for img in Input_Img_files:

    #read an image
    image = cv.imread(img)
    
    #make a copy of the image to work on
    draw_image = np.copy(image)
    
    #Initialize an image for generating a heatmap image
    heat_map_img = np.zeros_like(image[:,:,0]).astype(np.float)
    
    #Declare the values of xy_Windows, y_lim and xy_Overlap
    xy_Windows = [(86,59)]
    
    y_lim = [[341,401]]
    
    xy_Overlap = [(0.81,0.81)]
    
    #Build a list of windows using sliding window func
    windows_temp_1 = []

    #Loop through all the windows
    for i in range(len(xy_Windows)):
    
        #store the windows to search for cars
        windows_1 = sliding_window(image, [None, None], y_lim[i], xy_Windows[i], xy_Overlap[i])
        
        #append the windows to a list
        windows_temp_1.append(windows_1)

    #Flatten the windows list to 1-D list
    windows_final_1 = sum(windows_temp_1, [])
    
    #print(windows_final_1)
    
    #Declare values for orient, pixels_per_cell and cells_per_block
    
    orient = 9 #HOG orientations
    
    pixels_per_cell = 16 #HOG pixels per cell
    
    cells_per_block = 1 #HOG cells per block
    
    #search for cars in the windows one by one
    detected_car_windows = search_window_for_cars(image, windows_final_1, svc, X_Scaler, orient, pixels_per_cell, cells_per_block)
    
    #print(detected_car_windows)
    
    #Draw the detected cars on the image
    detected_car_img = draw_bounding_box(draw_image, detected_car_windows, color=(0, 0, 255), thickness=6)

    #Generate a heat_map of the image so that we can reduce the false positives in the #image
    heat_map_img = add_heat_to_bounding_box_pixels(heat_map_img, detected_car_windows)
    
    #We will apply a threshold so that we can get our final image
    heat_map_img = apply_heatmap_threshold(heat_map_img, 2)
    
    #Visualize the heatmap image. Apply clip to bring it in range so that we can #visualize it
    heatmap_img = np.clip(heat_map_img, 0, 255)
    
    #Label the image so that we can generate our final image with reduced false positives
    labels_img = label(heatmap_img)
    
    #Generate the final image of the dectected cars
    draw_image = draw_bounding_boxes_labels(np.copy(image), labels_img)
    
    fig = plt.figure(figsize=(10,10))
    
    plt.subplot(131)
    
    plt.imshow(detected_car_img)
    
    plt.title("Cars detected")
    
    plt.subplot(132)
    
    plt.imshow(heatmap_img, cmap='hot')
    
    plt.title('Heat Map image')
    
    plt.subplot(133)
    
    plt.imshow(draw_image, cmap='hot')
    
    plt.title('Final Image')
    
    plt.tight_layout()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09050895477081858, 'fraction_numerical': 0.01927552362642922, 'mean_word_length': 3.3732300884955753, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '17', 'dir': 'jupyter-structured-clean-dedup', 'id': '240848', 'license': 'MIT', 'n_tokens_mistral': 6952, 'n_tokens_neox': 6559, 'n_words': 1919, 'path': 'COMP9517_Project/COMP9517_Individual_Part/COMP9517_Project.ipynb', 'repo_name': 'usama-sadiq/COMP9517_21T1', 'size': '19766'}