|
""" |
|
VGGNet Keras Implementation |
|
|
|
This module provides an implementation of the VGGNet architecture using Keras. |
|
It contains functions to create VGG16 and VGG19 models, as well as utility |
|
functions to preprocess images for use with the models. |
|
""" |
|
|
|
from keras.optimizers import SGD |
|
from keras.models import Sequential |
|
import cv2 as opencv |
|
import numpy as np |
|
from keras.layers import Dense, Dropout, Flatten, MaxPooling2D, ZeroPadding2D,\ |
|
Convolution2D |
|
|
|
|
|
def vgg16(): |
|
""" |
|
Creates a VGG16 model using Keras. |
|
|
|
Returns: |
|
model (Sequential): The VGG16 model. |
|
""" |
|
|
|
model = Sequential() |
|
|
|
# Define the VGG16 architecture. |
|
# Add layers, each block represents a group of layers in the VGG16 model |
|
|
|
# 224 x 224 x 3 |
|
model = Sequential() |
|
model.add(ZeroPadding2D((1, 1), input_shape=(224, 224, 3))) |
|
model.add(Convolution2D(64, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(64, 3, 3, activation='relu')) |
|
model.add(MaxPooling2D((2, 2), strides=(2, 2))) |
|
|
|
# 224 x 225 x 64 |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(128, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(128, 3, 3, activation='relu')) |
|
model.add(MaxPooling2D((2, 2), strides=(2, 2))) |
|
|
|
# 112 x 112 x 128 |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(256, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(256, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(256, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(256, 3, 3, activation='relu')) |
|
model.add(MaxPooling2D((2, 2), strides=(2, 2))) |
|
|
|
# 56 x 56 x 256 |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(512, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(512, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(512, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(512, 3, 3, activation='relu')) |
|
model.add(MaxPooling2D((2, 2), strides=(2, 2))) |
|
|
|
# 28 x 28 x 512 --- # 14 x 14 x 512 --- # 1 x 1 x 1000 |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(512, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(512, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(512, 3, 3, activation='relu')) |
|
model.add(ZeroPadding2D((1, 1))) |
|
model.add(Convolution2D(512, 3, 3, activation='relu')) |
|
model.add(MaxPooling2D((2, 2), strides=(2, 2))) |
|
|
|
# 1 x 1 x 4096 --- # 1 x 1 x 1000 |
|
model.add(Flatten()) |
|
model.add(Dense(4096, activation='relu')) |
|
model.add(Dropout(0.5)) |
|
model.add(Dense(4096, activation='relu')) |
|
model.add(Dropout(0.5)) |
|
model.add(Dense(1000, activation='softmax')) |
|
|
|
# Load Weights |
|
model.load_weights('./vgg16_weights.h5') |
|
|
|
return model |
|
|
|
|
|
def vgg19(): |
|
""" |
|
Placeholder function for VGG19. |
|
""" |
|
return False |
|
|
|
|
|
def preprocess_image(image_path): |
|
""" |
|
Preprocess an image for use with VGGNet models. |
|
|
|
Args: |
|
image_path (str): Path to the input image file. |
|
|
|
Returns: |
|
im (numpy.ndarray): Preprocessed image. |
|
""" |
|
|
|
image = opencv.imread(image_path) |
|
im = opencv.resize(image, (224, 224)).astype(np.float32) |
|
|
|
# Subtract mean RGB values for VGGNet |
|
im[:, :, 0] -= 103.939 |
|
im[:, :, 1] -= 116.779 |
|
im[:, :, 2] -= 123.68 |
|
im = im.transpose((2, 0, 1)) |
|
im = np.expand_dims(im, axis=0) |
|
|
|
return im |
|
|
|
|
|
def main(): |
|
""" |
|
Main function to run the VGGNet model on an input image. |
|
""" |
|
|
|
image_path = 'cat.jpg' |
|
|
|
# Preprocess the input image |
|
im = preprocess_image(image_path) |
|
|
|
# Load the model |
|
model = vgg16() |
|
|
|
# Compile the model |
|
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True) |
|
model.compile(optimizer=sgd, loss='categorical_crossentropy') |
|
|
|
# Predict using the model |
|
out = model.predict(im) |
|
print(np.argmax(out)) |
|
|
|
|
|
if __name__ == '__main__': |
|
main() |