YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

Import necessary modules

import tensorflow as tf from tensorflow import keras import numpy as np !pip install gradio import gradio as gr from tensorflow.keras.models import load_model from tensorflow.keras.utils import custom_object_scope

Import preprocessing layers directly from tensorflow.keras

from tensorflow.keras import layers

class RGBToGrayscaleLayer(keras.layers.Layer): def init(self, **kwargs): super().init(**kwargs)

def call(self, inputs):
    return tf.image.rgb_to_grayscale(inputs)

class GrayscaleToRGBLayer(keras.layers.Layer): def init(self, **kwargs): super().init(**kwargs)

def call(self, inputs):
    # Ensure input has a channel dimension
    if inputs.shape.rank == 3:  # Shape: (None, 224, 224)
        inputs = tf.expand_dims(inputs, axis=-1)  # Shape: (None, 224, 224, 1)
    return tf.image.grayscale_to_rgb(inputs)

def compute_output_shape(self, input_shape):
    return input_shape[:-1] + (3,)  # Output has 3 channels

Define ImageEnhancementLayer

class ImageEnhancementLayer(keras.layers.Layer): def init(self, **kwargs): super().init(**kwargs)

def call(self, inputs):
    if tf.executing_eagerly():
        # PIL-based enhancements (for debugging and visualization)
        img = tf.keras.preprocessing.image.array_to_img(inputs[0])  # Access first image in batch
        brightness_factor = 1 + (34 / 100)
        x_enhanced = ImageEnhance.Brightness(img).enhance(brightness_factor)
        contrast_factor = 1 + (30 / 100)
        x_enhanced = ImageEnhance.Contrast(x_enhanced).enhance(contrast_factor)
        sharpness_factor = 1 + (70 / 100)
        x_enhanced = ImageEnhance.Sharpness(x_enhanced).enhance(sharpness_factor)
        x_enhanced = x_enhanced.filter(ImageFilter.MedianFilter(size=1))

        # Convert back to tensor
        x_enhanced = tf.keras.preprocessing.image.img_to_array(x_enhanced)
        x_enhanced = tf.expand_dims(x_enhanced, 0)  # Restore batch dimension
        x_enhanced = tf.cast(x_enhanced, inputs.dtype)
    else:
        # Placeholder for TensorFlow-based enhancements during training
        x_enhanced = inputs
    return x_enhanced

Define StrokeWidthLayer

class StrokeWidthLayer(keras.layers.Layer): def init(self, **kwargs): super().init(**kwargs)

def call(self, inputs):
    # Placeholder for stroke width computation logic
    return inputs

class RobertsLayer(layers.Layer): def call(self, inputs): # Convert inputs to float32 inputs_float32 = tf.cast(inputs, tf.float32)

    # Check the number of channels
    num_channels = inputs.shape[-1]

    # Define Roberts Cross kernels
    kernel_x = tf.constant([[1, 0], [0, -1]], dtype=tf.float32)
    kernel_y = tf.constant([[0, 1], [-1, 0]], dtype=tf.float32)

    # Reshape kernels to match the number of input channels
    kernel_x = tf.reshape(kernel_x, [2, 2, 1, 1])
    kernel_y = tf.reshape(kernel_y, [2, 2, 1, 1])

    # Apply convolution using Roberts Cross kernels for each channel
    grad_x = [tf.nn.conv2d(inputs_float32[..., i:i+1], kernel_x, strides=[1, 1, 1, 1], padding='SAME') for i in range(num_channels)]
    grad_y = [tf.nn.conv2d(inputs_float32[..., i:i+1], kernel_y, strides=[1, 1, 1, 1], padding='SAME') for i in range(num_channels)]

    # Concatenate the gradients along the channel dimension (if more than one channel)
    grad_x = tf.concat(grad_x, axis=-1)
    grad_y = tf.concat(grad_y, axis=-1)

    # Compute the gradient magnitude
    grad_magnitude = tf.sqrt(tf.square(grad_x) + tf.square(grad_y))

    # Normalize the gradient magnitudes
    grad_magnitude /= tf.reduce_max(grad_magnitude)

    # Return the result with the same number of channels as input
    return grad_magnitude

def compute_output_shape(self, input_shape):
    return input_shape

class MorphologicalLayer(layers.Layer): def init(self, kernel_size=(2, 2), **kwargs): super(MorphologicalLayer, self).init(**kwargs) self.kernel_size = kernel_size

def call(self, inputs):
    # Ensure inputs have the shape (batch_size, height, width, 1) for grayscale
    if inputs.shape[-1] != 1:
        raise ValueError("Input must be a grayscale image with a single channel.")

    # Define the kernel for dilation and erosion
    kernel = tf.ones(tuple(self.kernel_size) + (1,), dtype=tf.float32)

    # Perform dilation
    dilated_image = tf.image.extract_patches(
        images=inputs,
        sizes=[1, self.kernel_size[0], self.kernel_size[1], 1],
        strides=[1, 1, 1, 1],
        rates=[1, 1, 1, 1],
        padding='SAME'
    )
    dilated_image = tf.reduce_max(dilated_image, axis=-1, keepdims=True)

    # Perform erosion
    eroded_image = tf.image.extract_patches(
        images=dilated_image,
        sizes=[1, self.kernel_size[0], self.kernel_size[1], 1],
        strides=[1, 1, 1, 1],
        rates=[1, 1, 1, 1],
        padding='SAME'
    )
    eroded_image = tf.reduce_min(eroded_image, axis=-1, keepdims=True)
    return eroded_image

def compute_output_shape(self, input_shape):
    return input_shape  # Ensure output shape matches input shape

class SqueezeLayer(layers.Layer): def init(self, axis=-1, **kwargs): super(SqueezeLayer, self).init(**kwargs) self.axis = axis

def call(self, inputs):
    squeezed = tf.squeeze(inputs, axis=self.axis)  # Remove extra dimensions

    # If squeezed shape has 3 dimensions and we have grayscale images, restore the channel dimension
    if len(squeezed.shape) == 3:  # (batch, height, width) for grayscale image
        restored = tf.expand_dims(squeezed, axis=-1)  # (batch_size, 224, 224, 1)
    else:
        restored = squeezed  # No expansion needed, already 4D

    return restored

Load the model with custom layers

with keras.utils.custom_object_scope({ 'RGBToGrayscaleLayer': RGBToGrayscaleLayer, 'RobertsLayer': RobertsLayer, 'StrokeWidthLayer': StrokeWidthLayer, 'SqueezeLayer': SqueezeLayer, 'MorphologicalLayer': MorphologicalLayer, 'GrayscaleToRGBLayer': GrayscaleToRGBLayer }): final_model = load_model("/content/drive/Shared drives/CS FILES/Model/vgg16_roberts_model.h5")

Recompile the model (even if you're not training)

model.compile(optimizer=keras.optimizers.Adam(learning_rate=1e-3),

loss="categorical_crossentropy",

metrics=["accuracy", "precision"])

class_labels = ["Low Potential Dysgraphia", "Potential Dysgraphia"]

Diagnostic messages for each class

diagnostic_messages = { "Low Potential Dysgraphia": "It suggests a minimal impairment in writing; however, observing difficulty in hand grip and positioning may still be beneficial.", "Potential Dysgraphia": "It is highly recommended to consult a specialist for further evaluation and support." }

Define image size (must match the model input size)

image_size = (224, 224)

def preprocess_image(img): img = img.resize(image_size) img_array = np.array(img)

# Handle RGBA images (if the image has an alpha channel)
if img_array.shape[-1] == 4:
    img_array = img_array[..., :3]

img_array = np.expand_dims(img_array, 0) / 255.0
return img_array

def predict_image(img): img_array = preprocess_image(img) predictions = final_model.predict(img_array) # Use final_model for prediction predicted_class_index = np.argmax(predictions[0])

# Optionally print predictions for debugging
print(f"Prediction probabilities: {predictions[0]}")

class_label = class_labels[predicted_class_index]
diagnostic_prompt = diagnostic_messages[class_label]
return f"This handwriting is \"{class_label}\".\n\n{diagnostic_prompt}"

Create Gradio interface

def gradio_interface(image): prediction = predict_image(image) return prediction

title = "Dysgraphia Classification using VGG16 Architecture with Sobel Edge Detection in an Offline Handwriting Analysis" description = "Upload the handwritten image and the model will predict if it shows signs of low potential dysgraphia or potential dysgraphia."

gr.Interface( fn=gradio_interface, inputs=gr.Image(type="pil"), outputs=gr.Textbox(label="Output Prediction"), title=title, description=description ).launch(share=True)

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support