resizing images from 64x64 to 224x224 for the VGG model - python

Can we resize an image from 64x64 to 256x256 without affecting the resolution is that a way to add zero on new row and column in the new resized output I m working on vgg and I get an error while adding my 64x64 input image because vggface is a pertrained model that include an input size of 224
code:
from keras.models import Model, Sequential
from keras.layers import Input, Convolution2D, ZeroPadding2D, MaxPooling2D, Flatten, Dense, Dropout, Activation
from PIL import Image
import numpy as np
from keras.preprocessing.image import load_img, save_img, img_to_array
from keras.applications.imagenet_utils import preprocess_input
from keras.preprocessing import image
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
# from sup5 import X_test, Y_test
from sklearn.metrics import roc_curve, auc
from keras.models import Model, Sequential
from keras.layers import Input, Convolution2D, ZeroPadding2D, MaxPooling2D, Flatten, Dense, Dropout, Activation
from PIL import Image
import numpy as np
from keras.preprocessing.image import load_img, save_img, img_to_array
from keras.applications.imagenet_utils import preprocess_input
from keras.preprocessing import image
import matplotlib.pyplot as plt
# from sup5 import X_test, Y_test
from sklearn.metrics import roc_curve, auc
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
import numpy as np
model = VGG16(weights='imagenet', include_top=False)
from keras.models import model_from_json
vgg_face_descriptor = Model(inputs=model.layers[0].input
, outputs=model.layers[-2].output)
# import pandas as pd
# test_x_predictions = deep.predict(X_test)
# mse = np.mean(np.power(X_test - test_x_predictions, 2), axis=1)
# error_df = pd.DataFrame({'Reconstruction_error': mse,
# 'True_class': Y_test})
# error_df.describe()
from PIL import Image
def preprocess_image(image_path):
img = load_img(image_path, target_size=(224, 224))
img = img_to_array(img)
img = np.expand_dims(img, axis=0)
img = preprocess_input(img)
return img
def findCosineSimilarity(source_representation, test_representation):
a = np.matmul(np.transpose(source_representation), test_representation)
b = np.sum(np.multiply(source_representation, source_representation))
c = np.sum(np.multiply(test_representation, test_representation))
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
def findEuclideanDistance(source_representation, test_representation):
euclidean_distance = source_representation - test_representation
euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
euclidean_distance = np.sqrt(euclidean_distance)
return euclidean_distance
vgg_face_descriptor = Model(inputs=model.layers[0].input, outputs=model.layers[-2].output)
# for encod epsilon = 0.004
epsilon = 0.16
# epsilon = 0.095
retFalse,ret_val, euclidean_distance = verifyFace(str(i)+"test.jpg", str(j)+"train.jpg", epsilon)
verifyFace1(str(i) + "testencod.jpg", str(j) + "trainencod.jpg")
Error :
ValueError: operands could not be broadcast together with
remapped shapes [original->remapped]:
(512,14,14)->(512,newaxis,newaxis) (14,14,512)->(14,newaxis,newaxis)
and requested shape (14,512)

I'm not sure what you mean, here is my solution for you.
First method, if i understand clearly what you mean, for adding pad with zero value you need to use numpy.pad for each layer of image.
I use this image for take example, its shape is 158x84x3
import numpy as np
import cv2
from matplotlib import pyplot as mlt
image = cv2.imread('zero.png')
shape = image.shape
add_x = int((256-shape[0])/2)
add_y = int((256-shape[1])/2)
temp_img = np.zeros((256,256,3),dtype = int)
for i in range(3):
temp_img[:,:,i] = np.pad(image[:,:,i],((add_x,add_x),(add_y,add_y)),'constant', constant_values = (0))
mlt.imshow(temp_img)
By this code i can add padding into picture and have the result like this.
Now its shape is 256x256x3 like you want.
Or another method for you is use Image of Pillow library. By using that, you can resize the picture without losing too much information with very simple code.
from PIL import Image
image = Image.fromarray(image)
img = image.resize((256, 256), Image.BILINEAR)
mlt.imshow(img)
That code will give you this solution
Hope my answer can help you solve the problem!

I think the best way to solve your problem is not resizing the image but rather to load the model specifying the input shape of your images.
Assuming you are using keras:
model = VGG16(weights=..., include_top=False, input_shape=(64,64,3))
Include top has to be set to false in order to change the input shape, which means you will need to do some sort of training yourself.
If you need include_top to be True resizing the input image is the best way to proceed, but a network trained on 224x224 images is probably not going to perform great with upscaled 64x64 images.

I think you mean resize (resolution) without increasing the size (amount of data)
and as far as I'm aware, the answer would be no, because making the resolution bigger literally would mean a higher pixel count. You could resize the resolution without increasing the file size too much though, there are plenty of programs, websites and utilities for lightweight photo resizing, maybe you could implement the use of a service like such into your code?

Related

Displaying image from a pytorch model

Having read a paper about demoireing image, I want to see how effective the method is. Given that the whole dataset is 100gbs, I only used 1gb worth of data to train a new one. And in the code below, I'm trying to display the image spitted out by the model. However, the image color is either messed up or in grayscale and holds no visual feature to the source of it which is a moire infected image. So I want to know if it was the small train dataset for the model to behave such way or me not showing the image properly
Example:
source
from_model
other
The code that i tried to display it:
import numpy as np
import os
import math
import torch
from tqdm import tqdm
from utils import MoirePic
from torch.utils.data import DataLoader
from torchvision.io import read_image
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt
def psnr(img1, img2):
mse = np.mean((img1 - img2) ** 2)
if mse == 0:
return 100
return 10 * math.log10(1 / mse)
def Test():
device = "cpu"
root = './Train_Data2'
dataset = MoirePic(os.path.join(root, 'source'),
os.path.join(root, 'target'))
test_loader = DataLoader(dataset=dataset, batch_size=1, drop_last=False)
model = torch.load('./moire_best.pth',map_location=torch.device('cpu') )
model.eval()
loop = tqdm(enumerate(test_loader), total=len(test_loader), leave=False)
psnr_all=0
for idx, (data, target) in loop:
with torch.no_grad():
output = model(data).cpu()
transform = transforms.ToPILImage()
img = transform(output[0])
img.show()
print(psnr(output[0].numpy(), target[0].numpy()))
Test()
The PSNR i got from them 2 is 19.55170616098589
My trained model - https://drive.google.com/file/d/1xuCX7A48MvJU4V3BkvwFLjgccOE2_eBi/view?usp=sharing
The link to the paper : https://paperswithcode.com/paper/moire-photo-restoration-using-multiresolution
The link to the implementation: https://github.com/ZhengJun-AI/MoirePhotoRestoration-MCNN

'NoneType' object has no attribute 'register_forward_hook' error

I have been getting this error 'NoneType' object has no attribute 'register_forward_hook' when I run my code. I believe that there is something wrong with my function but not too sure what is the problem. If not is there a better way to get the feature vectors? I am trying to extract the Feature Vectors from a pretrained model from a resnet pretrained algorithm. Help would be much appreciated.
Here is the code.
import torch
import torch.nn as nn
import torchvision.models as models
import numpy as np
from torch.autograd import Variable
from torchvision import datasets, transforms,models
import torch.nn.functional as F
import torch.nn as nn
import torchvision.utils as vutils
from io import open
import os
from PIL import Image
import sys
import models.resnet as ResNet
import models.senet as SENet
import torchvision.models as models
import pickle
import pandas as pd
import sklearn.metrics
import matplotlib.pyplot as plt
from models import resnet, resnet50_ferplus_dag, resnet50_ft_dag, resnet50_scratch_dag, senet, senet50_ferplus_dag, senet50_ft_dag, senet50_scratch_dag, vgg_face_dag, vgg_m_face_bn_dag
model = resnet50_ft_dag.resnet50_ft_dag(weights_path='Weights/resnet50_ft_dag.pth') # RESNET MS1M
layer = model._modules.get('avgpool')
model.eval()
scaler = transforms.Scale((224, 224))
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
to_tensor = transforms.ToTensor()
def get_vector(image):
# Load image
img = Image.open(image)
# Create Pytorch variable with transformed image
t_img = Variable(normalize(to_tensor(scaler(img))).unsqueeze(0))
# Create a vector of zeros that will hold our feature vector
# Outputsize of 2048
my_embedding = torch.zeros(2048)
# Define a function that will copy the output of a layer
def copy_data(m, i, o):
my_embedding.copy_(o.data)
# Attach that function to our selected layer
h = layer.register_forward_hook(copy_data)
# Run model on transformed image
model(t_img)
# Detach our copy function from the layer
h.remove()
# Return the feature vector
return my_embedding
get_vector('C:/Users/Public/Documents/DIN_Image/average_images/' + list_dir[2])

Testing a Random Image against a Python Keras/Tensorflow CNN

I've created and CNN and I am trying to figure out how to test a random image against it. I am utilizing Keras and Tensorflow. Lets assume I wanted to test the image found here: https://i.ytimg.com/vi/7I8OeQs7cQA/maxresdefault.jpg.
How would I save the model, load it then test this image against it? Here is some example code I found online that demonstrates what I mean:
https://meta.stackexchange.com/questions/144665/hide-email-address-from-my-profile
Any help is much appreciated, thanks!
import os
import cv2
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import display, Image
from keras.models import Sequential, load_model
from keras.layers import Conv2D, Flatten, MaxPooling2D, Input
from keras.preprocessing.image import ImageDataGenerator
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import models, layers
X = []
y = []
from sklearn.model_selection import train_test_split
labels = os.listdir(r'C:/Users/zF1bo/Desktop/natural_images')
labels
for label in labels:
path = r'C:/Users/zF1bo/Desktop/natural_images/{}/'.format(label)
img_data = os.listdir(path)
for image in img_data:
a = cv2.imread( path + image)
a = cv2.resize(a, (64, 64))
X.append(np.array(a.astype('float32')) / 255)
y.append(label)
buckets = []
for i in y:
if i == 'airplane':
buckets.append(0)
elif i == 'car':
buckets.append(1)
elif i == 'cat':
buckets.append(2)
elif i == 'dog':
buckets.append(3)
elif i == 'flower':
buckets.append(4)
elif i == 'fruit':
buckets.append(5)
elif i == 'motorbike':
buckets.append(6)
elif i == 'person':
buckets.append(7)
y = buckets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, \
random_state = 0)
model = models.Sequential()
model.add(layers.Conv2D(filters=32, kernel_size=(5,5), activation='relu', input_shape=(64,64,3)))
model.add(layers.MaxPool2D(pool_size=(2, 2)))
model.add(layers.Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(layers.MaxPool2D(pool_size=(2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(8, activation='softmax'))
model.compile(optimizer='adam', loss = 'sparse_categorical_crossentropy',metrics=['accuracy'])
y_train = np.array(y_train)
model.fit(X_train, y_train, batch_size=(256), epochs=25)
pred = model.predict(X_test)
diff = []
for i in pred:
diff.append(np.argmax(i))
from sklearn.metrics import accuracy_score
accuracy_score(diff,y_test)
Step 1: Save the model
model.save('model.h5')
Step 2: Load the model
loaded_model = tensorflow.keras.models.load_model('model.h5')
Step 3: Download the image via requests library(answer is taken from: Downloading a picture via urllib and python):
import urllib.request
urllib.request.urlretrieve(url, filename)
Otherwise you can apply the same steps like in the first picture you posted. Do not forget to expand_dims()
you can save your model using mode.save('path to save location')
To input an image you should read it, perform any pre-processing that you did to the training images then use model.predict as shown in the code below.
import tensorflow as tf
from tensorflow import keras
model = keras.models.load_model('path/to/location') # loads the saved model
pred_img =r'path to the img'
img=cv2.imread (pred_img)
img=img/255 # rescale the image
print(img.shape)
img=cv2.resize(img, (64,64)) # resize to same size used in training
print (img.shape)
img=np.expand_dims(img, axis=0)
print (img.shape)
pred=model.predict(img)
print (pred) # will be a list of 8 elements select the element in the list with the highest probability
index=np.argmax(pred)) # this will be the index of the class predicted
class_name=buckets[index] # this will be the name of the class predicted
print (class_name)
NOTE if your read in the training images with cv2 remember the order is bgr not rgb. The model was trained on bgr images. When you read in the image to predict it must be bgr also.

Keras( with Tensorflow 2 backend) error while visualizing Layer outputs

I am using Keras with tensorflow 2.0 and I am classifying image using Mobilenetv2_.
The code for training and validation works fine. Now, i want to visualize activation of certain layers.
Here is part of my code:
from __future__ import print_function
from datetime import datetime
import numpy as np
import matplotlib.pyplot as plt
from sklearn.utils import class_weight
from tensorflow.keras import backend as k
k.backend.image_data_format= 'channels_last' # for remote run
from tensorflow.keras import layers
from tensorflow.keras.preprocessing.image import ImageDataGenerator,load_img,img_to_array
from tensorflow.keras import optimizers,models
from keras.models import model_from_json
from tensorflow.keras.applications import InceptionResNetV2,MobileNetV2
from tensorflow.keras.applications.inception_resnet_v2 import preprocess_input
from tensorflow.keras.callbacks import ModelCheckpoint
from tensorflow.keras.callbacks import ReduceLROnPlateau
#import cv2
from tensorflow.keras.callbacks import TensorBoard
from tensorflow.keras.utils import multi_gpu_model
from helper_func import save_batch_info,smooth_curve,save_model_hyperparam,save_plots,get_batch_stats
import tensorflow as tf
import os
# ********** SOME CODE HERE *************************
def Mobilenetv2_finetune_model():
MobileNet_tuned = MobileNetV2(weights='C:\\ML\\mobilenet_v2_weights_tf_dim_ordering_tf_kernels_1.0_96_no_top.h5'
, include_top=False,input_shape=(W_rz, H_rz, nc),alpha =1)
#If alpha < 1.0, proportionally decreases the number of filters in each layer.
# If alpha > 1.0, proportionally increases the number of filters in each layer.
model = models.Sequential()
model.add(MobileNet_tuned)
model.add(layers.Flatten())
model.add(layers.Dropout(0.1))
model.add(layers.Dense(nclass, activation='softmax'))
return model,MobileNet_tuned
model,conv_bs = Mobilenetv2_finetune_model()
#****************** Visualizing intermediate activations ***************
layer_outputs = [layer.output for layer in model.layers[0].layers[:17]]
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)
img_pth = 'C://ML//test//52.png'
img_tst = img_to_array(load_img(img_pth, target_size=(96,96)))
activations = activation_model.predict(img_tst)
As I run this,I get error as below:
This is coming from line
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)
What am I doing wrong here? I followed Francois Chollet's book, and it was used similarly there.
Any help is greatly appreciated.
sedy

ValueError: Error when checking input: expected flatten_input to have 3 dimensions, but got array with shape (22, 12)

I am new to Tensorflow, I am trying to do text recognize for image(size 12x22) using tensorflow.
Training model seems to be ok, but when do prediction, there is error:
File "C:\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training_utils.py", line 316, in standardize_input_data
'with shape ' + str(data_shape))
ValueError: Error when checking input: expected flatten_input to have 3 dimensions, but got array with shape (22, 12)
I don't know why it needs 3 dimension while I just input a image in 2D.
train_model.py, this is the trainer, export a training model
import cv2
import pickle
import os.path
import numpy as np
from imutils import paths
import tensorflow as tf
# from sklearn.preprocessing import LabelBinarizer
# from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
# from keras.layers.convolutional import Conv2D, MaxPooling2D
from tensorflow.keras.layers import Flatten, Dense
import image_fit
LETTER_IMAGES_FOLDER = "training_generate/divided_sample"
MODEL_FILENAME = "captcha_model.hdf5"
MODEL_LABELS_FILENAME = "model_labels.dat"
# initialize the data and labels
data = []
labels = []
# loop over the input images
print('Read images')
for image_file in paths.list_images(LETTER_IMAGES_FOLDER):
# Load the image and convert it to grayscale
image = cv2.imread(image_file)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# resize the image as 12, 22
image = image_fit.resize_to_fit(image, 12, 22)
# Grab the name of the letter based on the folder it was in
label = image_file.split(os.sep)[-2]
label = chr(int(label))
# Add the letter image and it's label to our training data
data.append(image)
labels.append(label)
print('Done reading')
data = tf.keras.utils.normalize(np.array(data), axis=1)
# print(data[0])
labels = np.array(labels)
model = Sequential()
model.add(Flatten(input_shape=(22, 12)))
model.add(Dense(128, activation=tf.nn.relu))
model.add(Dense(128, activation=tf.nn.relu))
model.add(Dense(62, activation=tf.nn.softmax))
model.compile(optimizer='Adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(data, labels, epochs=3)
print('Finish training')
# val_loss, val_acc = model.evaluate()
model.save(MODEL_FILENAME)
solve.py, this is the python script that solve the letter.
import cv2
import pickle
import os.path
import numpy as np
from imutils import paths
import tensorflow as tf
import image_fit
LETTER_IMAGES_FOLDER = "training_generate/divided_sample"
MODEL_FILENAME = "captcha_model.hdf5"
MODEL_LABELS_FILENAME = "model_labels.dat"
image_file = 'test_0.bmp'
image = cv2.imread(image_file)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = image_fit.resize_to_fit(image, 12, 22)
new_model = tf.keras.models.load_model(MODEL_FILENAME)
predicitions = new_model.predict(image)
print(np.argmax(predicitions[0]))
When you make the prediction with the line
predicitions = new_model.predict(image)
it is expecting the first dimension to be the number of images in the batch. Since you only have one image, the first dimension would be of size one. You could resize the image to be (1,22,12), and this would pass:
predicitions = new_model.predict(image.reshape(1,22,12))
According to Kruger's answer, the code should be look like this:
image_file = 'test_0.bmp'
image = cv2.imread(image_file)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = image_fit.resize_to_fit(image, 12, 22)
data = [image]
new_model = tf.keras.models.load_model(MODEL_FILENAME)
predicitions = new_model.predict(np.array(data))
print(np.argmax(predicitions[0]))

Categories