I’ve had success applying (a part of) VGG16 to images of a different size.
The thing is, in a Convolutional Layer, all weights are shared between kernels on each pixel of the image, so the actual image dimensions do not matter. Or to put it differently: a convolution is a translation-invariant operation, it does depend on where on the image it is applied.
That means you can freely resize the input to a Conv2D layer, and it’s output will similarly change. Of course, the original VGG16 pipes into a few Dense layers that do depend on input size, and they are also trained for a certain dimension.
You can also see that the ConvBlocks in Jeremy’s VGG code do not mention the input size anywhere:
model.add(Conv2D(filters, (3, 3), activation='relu'))
The only place where the input size is taken into account is in the very first layer that applies the initial image preprocessing:
model.add(Lambda(vgg_preprocess, input_shape=(3,224,224), output_shape=(3,224,224)))
Keras is smart, it propagates this shape to the rest of the model, but you are free to modify it. However, if you do, you can no longer use the pre-trained weights from the Fully Connected blocks, because they were trained to accept the dimensions that are output from the final Conv block. (7x7x512 if I am not mistaken)