I'm decoding a base64 image with the following code:
def string_to_image(base64_string):
decoded = base64.b64decode(base64_string)
np_data = np.frombuffer(decoded, np.uint8)
img = cv2.imdecode(np_data, cv2.IMREAD_UNCHANGED)
return img
The goal is to receive an image from the request body, decode it, resize it with tensorflow, predict it with a model, and return a response saying what is that image:
image_base64 = request.json['image']
decoded_image = string_to_image(image_base64)
image_resized = tf.image.resize(decoded_image, (256, 256))
model = load_model('src/models/mymodel.h5')
result = model.predict(np.expand_dims(image_resized/255, 0))
However, I'm getting the error ValueError: Input 0 of layer "sequential_2" is incompatible with the layer: expected shape=(None, 256, 256, 3), found shape=(None, 256, 256, 4).
I don't know how to change the Shape value from '4' to '3'.
I tried the following:
image_resized = tf.image.resize(decoded_image, (256, 256, 3))
But I get 'size' must be a 1-D Tensor of 2 elements: new_height, new_width.
I also tried:
image_resized = cv2.resize(decoded_image, (256,256,3))
But I get OpenCV(4.6.0) :-1: error: (-5:Bad argument) in function 'resize'
Overload resolution failed:
- Can't parse 'dsize'. Expected sequence length 2, got 3
- Can't parse 'dsize'. Expected sequence length 2, got 3
Please help :(
You could reshape the array by using tf.squeeze after reshaping the tensor. According to documentation, tf.squeeze will remove axis with dimensions 1.
image_resized = tf.reshape(decoded_image, (-1, 256, 256, 3, 1))
image_resized = tf.squeeze(image_resized)
With vijayachandran mariappan comment and AndreaYolo answer I figured out a solution. First, change the channels of the image and then resize its dimensions:
decoded_image = string_to_image(image_base64)
decoded_image = decoded_image[:,:,:3]
image_resized = tf.image.resize(decoded_image, (256, 256))
My model then was able to predict perfectly!
Related
I want to predict from image url. In the past, I use ImageDatagenerator().flow_from_directory() methods, but now I have only one image. so I want to predict from this single image.
I have tried the below code, but failed. (Dimension error)
url = "http://3.36.149.28/uploads/WEBUPLOADprofile.png"
img = Image.open(requests.get(url, stream=True).raw)
img = img_to_array(img)
img = img/255.
#Predict
pred = model.predict(img)
so I tried reshape & retrying, but failed (cannot reshape array of size 1048576 into shape (28,28,1))
img = img.reshape(-1, 28, 28, 1)
img = img/255.
#Predict
pred = model.predict(img)
for getting reshape & get colored predict image, what can I do ? please help..
Additional : I trained srcnn model, and inputs :
inputs = Input((None, None, 3), dtype='float')
I resolved this problem.
First, my url image shape is (None, None, 4), but my trained shape is (None, None, 3).
So I tried another jpg image (None, None, 3) and expand dimension via np,
and result shape = (1, None, None, 3)
image = np.expand_dims(image, axis=0)
model.predict(image)
from link
and now I get predict image successfully.
I am trying to read a custom mapped dataset for training. But after I map the dataset using a py_function, I get unknown shape like:
def process_path(file_path):
label = get_label(file_path)
img = tf.io.read_file(file_path)
img = decode_img(img)
print('image shape:', img.shape) #this print correctly: image shape: (180, 180, 3)
print('label shape:', label.shape) #this print correctly: label shape: ()
return img, label
train_ds = train_ds.map(lambda x: tf.py_function(process_path, [x], (tf.float32, tf.int32)))
print(train_ds)
# this print unknown shape <PrefetchDataset shapes: (<unknown>, <unknown>), types: (tf.float32, tf.int32)>
This will fail the model.fit(), so I want to reshape the dataset to the correct shape like:
<BatchDataset shapes: ((None, 180, 180, 3), (None,)), types: (tf.float32, tf.int32)>
using:
train_ds = tf.reshape(train_ds, ((None, 180, 180, 3), (None,)))
But this will give an error:
ValueError: Attempt to convert a value (<MapDataset shapes: (<unknown>, <unknown>), types: (tf.float32, tf.int32)>) with an unsupported type (<class 'tensorflow.python.data.ops.dataset_ops.MapDataset'>) to a Tensor.
How can I correctly assign the (image, label) shape in this step?
You don't need py_function here. Let's say you have a folder called /dogs that is full of jpg. You can use these two little functions to load and decode.
The first one returns 1 if the file name (e.g., 'dogs\\dog1.jpg') is in the folder dogs and 0 otherwise.
The second function also takes a file name and transforms it into float between 0 and 1. Then, it also resizes the picture.
Let me know if anything is unclear.
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
import tensorflow as tf
from glob2 import glob
os.chdir('c:/users/nicol/pictures')
files = glob('*/*jpg')
def get_label(file_path):
split = tf.strings.split(file_path, sep=os.sep)[0]
equal = tf.equal(split, 'dogs')
cast = tf.cast(equal, tf.int32)
return cast
def process_path(file_path):
label = get_label(file_path)
img = tf.io.read_file(file_path)
img = tf.image.decode_jpeg(img, channels=3)
img = tf.image.convert_image_dtype(img, tf.float32)
img = tf.image.resize(img, size=(180, 180))
return img, label
train_ds = tf.data.Dataset.from_tensor_slices(files).map(process_path)
next(iter(train_ds))
(<tf.Tensor: shape=(180, 180, 3), dtype=float32, numpy=
array([[[1.41176477e-01, 9.41176564e-02, 1.33333340e-01],
[1.41176477e-01, 9.41176564e-02, 1.33333340e-01],
[1.41176477e-01, 9.41176564e-02, 1.33333340e-01],
...,
[2.63300300e-01, 2.76176542e-01, 4.67582583e-01],
[2.46176332e-01, 2.59706050e-01, 4.50785339e-01],
[2.54726082e-01, 2.68909693e-01, 4.59662050e-01]]], dtype=float32)>,
<tf.Tensor: shape=(), dtype=int32, numpy=1>)
get_label should return an integer, if it's not already the case.
my model input shape is (50,50,1)
I am getting the frame by:
cv2.VideoCapture(0).read()
When I'm using np.reshape() function it does not reshape it the desired shape.
sized_frame = (cv2.resize(frame, (50,50)))
cv2.waitKey(0)
img_data = np.array(photo)
data = tf.reshape(img_data, (1,50,50,3))
model_out = model.predict([img_data])[0]
print(model_out)
if np.argmax(model_out) == 1:
str_label = 'Dog'
else:
str_label = 'Cat'
return str_label
This is the error I'm getting:
ValueError: Cannot feed value of shape (1, 50, 50, 3) for Tensor 'input/X:0', which has shape '(?, 50, 50, 1)'
The following code should solve your error
gray = cv2.cvtColor(photo, cv2.COLOR_BGR2GRAY)
img_data = np.array(gray)
data = tf.reshape(img_data, (1,50,50,1))
model_out = model.predict(img_data)[0]
Under the assumption that you trained on Grayscale images
enter code here
img = cv2.imread(f'resized_data/train/normal/IM-0115-0001.jpeg')
img2 = cv2.imread(f'resized_data/train/normal/IM-0117-0001.jpeg')
imgs = []
imgs.append(img)
imgs.append(img2)
imgs = np.array(imgs)
So I have two numpy.ndarray so far, with the shape of (256, 256, 3) each.
I append them to a list, which I will convert to a numpy ndarray later. When I call the imgs.shape function the shape is the following --> (2, ).
Why is the shape of the imgs array (2, ) and not (2, 256, 256, 3) ?
Thanks in advance.
When feeding an image to a pretrained InceptionResNetV2 network, I have the following results.
from keras.applications.inception_resnet_v2 import InceptionResNetV2
INPUT_SHAPE = (200, 250, 3)
img = load_img() # loads a 200x250 rgb image into a (200, 250, 3) numpy array
assert img.shape == INPUT_SHAPE # just fine
model = InceptionResNetV2(include_top=False, input_shape=INPUT_SHAPE)
model.predict(img)
ValueError: Error when checking input: expected input_1 to have 4 dimensions, but got array with shape (200, 150, 3)
I don't understand why and how the model expects a 4 dimension input. What must be done to adapt the (200, 250, 3) image so that it can be processed by the model?
try reshape your input with shapes (1, 200, 150, 3) or (200, 150, 3, 1).
You can use image = np.expand_dims(image, axis=0)) or
image = input_data.reshape((-1, image_side1, image_side2, channels))
You need to feed a batch of images. If your batch has one image, it should also have the same format.
try img.reshape((1, 200, 150, 3))