I'm using canva/konva.js to allow users to draw digits frontend and sending them to backend to do some image detection. I'm using EMNIST because I'm allowing all letters but my detection was very very very bad...
I originally thought it might be the data I was getting, but MNIST turns out to not work with it either.
Here's my detection code in python:
from extra_keras_datasets import emnist
(input_train, target_train), (input_test, target_test) = emnist.load_data(type='balanced')
input_train = tf.keras.utils.normalize(input_train, axis = 1)
input_test = tf.keras.utils.normalize(input_test, axis = 1)
def train():
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28, 28)))
model.add(tf.keras.layers.Dense(256, activation='relu'))
model.add(tf.keras.layers.Dense(256, activation='relu'))
model.add(tf.keras.layers.Dense(62, activation='softmax'))
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(input_train, target_train, epochs = 20)
Here's my canva code (using konva.js) :
<Stage
width={window.innerWidth/4}
height={window.innerHeight/3}
onMouseDown={handleMouseDown}
onMousemove={handleMouseMove}
onMouseup={handleMouseUp}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
id="stage"
ref={stageRef}
className="stage" >
<Layer>
<Rect
x={0}
y={0}
width={window.innerWidth}
height={window.innerHeight}
fill="white"
shadowBlur={0} />
{lines.map((line, i) => (
<Line
key={i}
points={line.points}
stroke="#000000"
strokeWidth={4}
tension={0.5}
lineCap="round"
lineJoin="round"
globalCompositeOperation={
line.tool === 'eraser' ? 'destination-out' : 'source-over'
}
/>
))}
</Layer>
</Stage>
Here's how I handle my images:
I did this because what I get is a black text on white background image.
I remove the whitespace and rotate it and invert the colour (because that's how it seems to look like).
I've tried making my strokes thicker in the canvas but it doesn't seem to work.
I'm just wondering how I can process my image/set up canvas so that it generates an image that EMNIST can detect?
img = opencv.remove_whitespace(path)
img = cv2.imread(path)[:, :, 0]
img = cv2.resize(img, (28, 28))
img = cv2.bitwise_not(img)
# img = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
# img = cv2.flip(img, 0)
cv2.imshow("img", img)
cv2.waitKey(0)
img = np.array([img])
model = tf.keras.models.load_model('model.model')
prediction = model.predict(img)
print("The predicted value is : ", prediction)
classes = np.argmax(prediction,axis=1)
print("Predicted class: ", classes)
Related
First of all i already load my model to predict inference set that i already prepared, but i got error when to try predict and show the result.
so here my code
def load_img(filename):
img = read_file(filename) # Load Data
img = decode_image(img, channels=3) # convert to RGB
img = resize(img, size=[img_height, img_height])
img = np.array(img)[:,:,1] # Resize image
img = img/255. # Rescale Images
return img
inf1 = load_img(r'ML2\COVID-19\inf_set\covid\covid - 1.jpeg')
inf2 = load_img(r'ML2\COVID-19\inf_set\covid\covid - 2.jpeg')
inf3 = load_img(r'ML2\COVID-19\inf_set\normal\Normal - 1.jpeg')
inf4 = load_img(r'ML2\COVID-19\inf_set\normal\Normal - 2.jpeg')
inf5 = load_img(r'ML2\COVID-19\inf_set\pneumonia\Pneumonia - 1.jpeg')
inf6 = load_img(r'ML2\COVID-19\inf_set\pneumonia\Pneumonia - 2.jpeg')
plt.figure(figsize=(35, 5))
plt.suptitle('Prediction Results', fontsize=15)
counter = 1
for i in [inf1,inf2, inf3, inf4, inf5,inf6]:
plt.subplot(1,6,counter)
res = int(tf.round(model.predict(x=expand_dims(i, axis=0))))
plt.imshow(i)
plt.title(f"Prediction: {label_data[res]}")
plt.axis('off')
counter += 1
plt.show()
And here the error notification
So, i need help to solve this proble, thank you before
You are squashing the image size in this line
img = np.array(img)[:,:,1]
This is why your image becomes size (220,220) instead of (220,220,1), which when you do expand_dims will be of proper input shape (1,220,220,1)
You could change the load_img function, or you could solve this by doing
res = int(tf.round(model.predict(x=expand_dims(i, axis=[0,3]))))
I am trying to augment all the satellite image(.TIFF format) at once but keep running into an error
Error: "('Input data in NumpyArrayIterator should have rank 4. You passed an array with shape', (0,))"
When i do it one at a time there is no error but when i run it in a folder it gives me the error.Can someone tell me what i am doing wrong
Thanks
from keras.preprocessing.image import ImageDataGenerator
from skimage import io
datagen = ImageDataGenerator(
rotation_range=45,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='constant', cval=125)
image_directory = 'E:\\opencv'
SIZE = 150
dataset = []
my_images = os.listdir(image_directory)
for i, image_name in enumerate(my_images):
if (image_name.split('.')[1] == 'TIFF'):
image = io.imread(image_directory + image_name)
image = Image.fromarray(image, 'RGB')
image = image.resize((SIZE,SIZE))
dataset.append(np.array(image))
x = np.array(dataset)
i = 0
for batch in datagen.flow(x, batch_size=16,
save_to_dir='E:\\opencv',
save_prefix='a',
save_format='TIFF'):
i += 1
if i > 20:
break
modify code as follows
for i, image_name in enumerate(my_images):
if (image_name.split('.')[1] == 'TIFF'):
fpath=os.path.join(image_directory, image_name)
print (fpath) # if this does not execute your if statement is incorrect
image = io.imread(fpath)
print (image.shape) # verify the image was read correctly
image = Image.fromarray(image, 'RGB')
image = image.resize((SIZE,SIZE))
print (image.size) # verify image was resized
dataset.append(np.array(image))
or
for i, image_name in enumerate(my_images):
if (image_name.split('.')[1] == 'TIFF'):
image = io.imread(image_directory + '/' + image_name)
image = Image.fromarray(image, 'RGB')
image = image.resize((SIZE,SIZE))
dataset.append(np.array(image))
The problem: I am unable to process CNN model for training 8-channel .TIF images.
Expected Output: Map training data (train_ds) via gdal and train model.
data (images):
n = 600
shape = (256, 256, 8)
data structure:
project_photos/
....classes/
......barren/
......agriculture/
......wooded/
import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
import tensorflow_datasets as tfds
import pathlib
>print (tf.__version__)
2.1.0
data_dir = ".\projects\keras\projectA\project_photos\classes")
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*.tif')))
>print(image_count)
600
list_ds = tf.data.Dataset.list_files(str(data_dir/'*/*'), shuffle=False)
list_ds = list_ds.shuffle(image_count, reshuffle_each_iteration=False)
batch_size = 32
img_height = 256
img_width = 256
>for f in list_ds.take(5):
> print(f.numpy())
b'/home/projects/keras/projectA/project_photos/classes/barren/12345_b0001.tif'
b'/home/projects/keras/projectA/project_photos/classes/wooded//12345_w0001.tif'
b'/home/projects/keras/projectA/project_photos/classes/barren/12345_b0002.tif'
b'/home/projects/keras/projectA/project_photos/classes/agriculture//12345_a0001.tif'
b'/home/projects/keras/projectA/project_photos/classes/wooded/12345_w0002.tif'
# tree structure
>class_names = np.array(sorted([item.name for item in data_dir.glob('*')]))
print(class_names)
['barren' 'agriculture' 'wooded']
# train/validation split
val_size = int(image_count * 0.2)
train_ds = list_ds.skip(val_size)
val_ds = list_ds.take(val_size)
def get_label(file_path):
# convert the path to a list of path components
parts = tf.strings.split(file_path, os.path.sep)
# The second to last is the class-directory
one_hot = parts[-2] == class_names
# Integer encode the label
return tf.argmax(one_hot)
def decode_img(img):
# convert the compressed string to a 3D uint8 tensor
img = tf.image.decode_jpeg(img, channels=3)
# resize the image to the desired size
return tf.image.resize(img, [img_height, img_width])
def process_path(file_path):
label = get_label(file_path)
# load the raw data from the file as a string
img = tf.io.read_file(file_path)
img = decode_img(img)
return img, label
# Set `num_parallel_calls` so multiple images are loaded/processed in parallel.
train_ds = train_ds.map(process_path, num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(process_path, num_parallel_calls=AUTOTUNE)
I understand that tensorflow has limited support (experimental) for decode_tiff, and even if that did work - I am unable to use the latest version of TF that has that update.
This leaves me with attempting workarounds, the following - which have not succeeded:
"""
Updating decode_img(img) in attempt to process 8-channel .TIF raster
"""
#attempt, adding gdal_Open variable to decode_img
## fails due to image path (train_ds) being stored as byte.
x = gdal.Open(file_path)
Error: Not a string.
#attempt, modifying to extract PATH as str().
def process_path(file_path):
label = get_label(file_path)
# load the raw data from the file as a string
img = ''
for fpath in file_path:
img = fpath.numy()
img = decode_img(img)
return img, label
>train_ds = train_ds.map(process_path, num_parallel_calls=AUTOTUNE)
ValueError: len requires a non-scalar tensor, got one of shape Tensor("Shape:0", shape=(0,), dtype=int32)
#attempt, processing outside of `.map`, works just fine.
imgList = []
for elem in train_ds:
img = elem.numpy()
img = img.decode()
imgList.append(img)
file_path = imgList[0]
raster = gdal.Open(file_path)
bands = [raster.GetRasterBand(k + 1).ReadAsArray() for k in range (raster.RasterCount)]
n_bands = len(bands)
img_array = np.stack(bands,2)
img = tf.convert_to_tensor(img_array, dtype = tf.float32)
img = tf.image.resize(img, [img_height, img_width])
print(type(img))
print(img.numpy().shape)
<class: 'tensorflow.python.framework.ops.EagerTensor'>
(256, 256, 8)
So, any ideas on how I can get this to work within the TF framework - getting TF to process the raster via .map?
So I've got a sequential model from mostly following along with this video. I've also got a drawing app done in JS and am sending the contents of that canvas to a flask server using JQuery. All of that seems to be working fine but when I give my model the image from the canvas and call predict it always gives me back the same exact response. The values at each index are always the same.
Am I missing something simple? Am I calling the predict wrong in the server or is it something to do with the model itself? It gets the predictions correct in the notebook.
Thanks for your time!
Flask server:
model = load_model('MyModel.h5')
imageWidth = 28
imageHeight = 28
dim = (imageWidth, imageHeight)
# Create the flask web application
app = fl.Flask(__name__)
#app.route('/uploadimage', methods = ['GET', 'POST'])
def uploadimage():
# Get the image from the request
theImage = fl.request.values.get("theImage", "")
#Decode the string to an image
decodedimg = base64.b64decode(theImage[22:])
# Save the image
with open ("theImage.png", "wb") as f:
f.write(decodedimg)
# Open the image from the request as originalImage
originalImage = Image.open("theImage.png")
# Resize it
resizedImage = ImageOps.fit(originalImage, dim, Image.ANTIALIAS)
# Confirm the dimensions of the resized image
w1, h1 = resizedImage.size
print(w1, h1)
# Save it locally
resizedImage.save("resizedImage.png", quality=100, optimize=True)
# Convert to grayscale and then convert that to an array
grayscaleImage = ImageOps.grayscale(resizedImage)
grayscaleArray = np.array(grayscaleImage)
grayscaleArray.shape # Gives (20, 20)
grayscaleArray = grayscaleArray.reshape(1, 28, 28)
setPrediction = model.predict(grayscaleArray)
print(setPrediction) # Always gives back same values
getPrediction = np.array(setPrediction[0])
predictedNumber = str(np.argmax(getPrediction))
print(predictedNumber) # Always '5'
return predictedNumber
Model:
model = kr.models.Sequential() # Create a new sequential neural network
model.add(kr.layers.Flatten()) # Input layer
model.add(kr.layers.Dense(128, activation="relu")) # 128 neurons and the 'basic' activation function.
model.add(kr.layers.Dense(128, activation="relu"))
model.add(kr.layers.Dense(10, activation="softmax"))
model.compile(loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]) # Played around with 'sgd' and 'rmsporp' optimizer also.
model.fit(X_train, y_train, epochs=3)
val_loss, val_acc = model.evaluate(X_test, y_test)
print(val_loss, val_acc)
I'm working on an algorithm to classify pictures of dogs and cats using Keras. As per the code below, this works when I feed in one image, but my question is can Keras.load_img work on multiple images in a folder? When I try this it says list object has no attributes seek and read.
from keras.preprocessing import image
test_image = image.load_img('dataset/single_prediction/cat_or_dog_1.jpg', target_size = (64, 64))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = classifier.predict(test_image)
training_set.class_indices
if result[0][0] == 1:
prediction = 'dog'
else:
prediction = 'cat'
I think there is a solution, you can try this:
images = []
for img in os.listdir(folder_path):
img = image.load_img(img, target_size=(img_width, img_height))
img = img.img_to_array(img)
img = np.expand_dims(img, axis=0)
images.append(img)
images = np.vstack(images)
classes = classifier.predict(images, batch_size=10)
print(classes)