Natwar's picture
Update app.py
5069bfa verified
raw
history blame contribute delete
8.63 kB
import os
import subprocess
import sys
import pkg_resources
import warnings
warnings.filterwarnings("ignore")
def install_package(package, version=None):
package_spec = f"{package}=={version}" if version else package
print(f"Installing {package_spec}...")
try:
subprocess.check_call([sys.executable, "-m", "pip", "install", "--no-cache-dir", package_spec])
except subprocess.CalledProcessError as e:
print(f"Failed to install {package_spec}: {e}")
raise
# Required packages
required_packages = {
"mediapipe": None,
"tensorflow": None,
"opencv-python-headless": None,
"gradio": None,
"Pillow": None,
"numpy": None
}
installed_packages = {pkg.key for pkg in pkg_resources.working_set}
for package, version in required_packages.items():
if package not in installed_packages:
install_package(package, version)
import numpy as np
import tensorflow as tf
import cv2
import mediapipe as mp
import gradio as gr
from PIL import Image
# Hand Tracker class - using the provided implementation
class handTracker():
def __init__(self, mode=False, maxHands=2, modelComplexity=1,
detectionConfidence=0.5, trackConfidence=0.5):
self.mode = mode
self.maxHands = maxHands
self.modelComplexity = modelComplexity
self.detectionConfidence = detectionConfidence
self.trackConfidence = trackConfidence
self.mpHands = mp.solutions.hands
self.hands = self.mpHands.Hands(
static_image_mode=self.mode,
max_num_hands=self.maxHands,
model_complexity=self.modelComplexity,
min_detection_confidence=self.detectionConfidence,
min_tracking_confidence=self.trackConfidence)
self.mpDraw = mp.solutions.drawing_utils
self.mpDrawStyles = mp.solutions.drawing_styles
def findAndDrawHands(self, frame):
RGBimage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.results = self.hands.process(RGBimage)
if self.results.multi_hand_landmarks:
for handLms in self.results.multi_hand_landmarks:
self.mpDraw.draw_landmarks(
frame,
handLms,
self.mpHands.HAND_CONNECTIONS,
self.mpDrawStyles.get_default_hand_landmarks_style(),
self.mpDrawStyles.get_default_hand_connections_style())
return frame
def findLandmarks(self, frame, handNo=0):
landmarkList = []
x_list = []
y_list = []
bbox = []
if self.results.multi_hand_landmarks:
if handNo < len(self.results.multi_hand_landmarks):
myHand = self.results.multi_hand_landmarks[handNo]
for id, lm in enumerate(myHand.landmark):
h, w, c = frame.shape
cx, cy = int(lm.x * w), int(lm.y * h)
x_list.append(cx)
y_list.append(cy)
landmarkList.append([id, cx, cy])
if x_list and y_list:
xmin, xmax = min(x_list), max(x_list)
ymin, ymax = min(y_list), max(y_list)
padding = 20
xmin = max(0, xmin - padding)
ymin = max(0, ymin - padding)
boxW = min(w - xmin, xmax - xmin + 2*padding)
boxH = min(h - ymin, ymax - ymin + 2*padding)
if boxW > boxH:
diff = boxW - boxH
ymin = max(0, ymin - diff//2)
boxH = min(h - ymin, boxW)
elif boxH > boxW:
diff = boxH - boxW
xmin = max(0, xmin - diff//2)
boxW = min(w - xmin, boxH)
bbox = [xmin, ymin, boxW, boxH]
return landmarkList, bbox
# Model loading with compatibility handling
def load_model_with_compatibility(model_path):
try:
model = tf.keras.models.load_model(model_path)
print("βœ“ Model loaded successfully")
return model
except Exception as e:
print(f"Standard loading failed: {str(e)}")
try:
class CustomDepthwiseConv2D(tf.keras.layers.DepthwiseConv2D):
def __init__(self, **kwargs):
if 'groups' in kwargs:
del kwargs['groups']
super(CustomDepthwiseConv2D, self).__init__(**kwargs)
custom_objects = {'DepthwiseConv2D': CustomDepthwiseConv2D}
model = tf.keras.models.load_model(
model_path,
custom_objects=custom_objects,
compile=False
)
print("βœ“ Model loaded in compatibility mode")
return model
except Exception as e2:
print(f"Compatibility loading failed: {str(e2)}")
return create_simple_asl_model()
def create_simple_asl_model():
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y']
print("Creating a new compatible model...")
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(len(labels), activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
model_path = "keras_model.h5"
model = load_model_with_compatibility(model_path)
model_input_shape = (224, 224, 3)
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y']
def preprocess_hand_roi(hand_roi, target_shape):
if target_shape[2] == 3:
if len(hand_roi.shape) == 2 or hand_roi.shape[2] == 1:
hand_roi_rgb = cv2.cvtColor(hand_roi, cv2.COLOR_GRAY2RGB)
else:
hand_roi_rgb = hand_roi.copy()
resized = cv2.resize(hand_roi_rgb, (target_shape[0], target_shape[1]))
normalized = resized.astype('float32') / 255.0
else:
if len(hand_roi.shape) > 2 and hand_roi.shape[2] > 1:
hand_roi_gray = cv2.cvtColor(hand_roi, cv2.COLOR_BGR2GRAY)
else:
hand_roi_gray = hand_roi
resized = cv2.resize(hand_roi_gray, (target_shape[0], target_shape[1]))
normalized = resized.astype('float32') / 255.0
if len(normalized.shape) == 2:
normalized = normalized[..., np.newaxis]
return np.expand_dims(normalized, axis=0), resized
def process_image(input_image):
frame = cv2.cvtColor(np.array(input_image), cv2.COLOR_RGB2BGR)
tracker = handTracker(detectionConfidence=0.7)
frame_with_hands = tracker.findAndDrawHands(frame.copy())
landmarks, bbox = tracker.findLandmarks(frame)
if not bbox:
return "No hand detected", None
x, y, w, h = bbox
hand_roi = frame[y:y+h, x:x+w]
cv2.rectangle(frame_with_hands, (x, y), (x+w, y+h), (0, 255, 0), 2)
model_input, _ = preprocess_hand_roi(hand_roi, model_input_shape)
try:
prediction = model.predict(model_input, verbose=0)[0]
predicted_class = np.argmax(prediction)
confidence = np.max(prediction)
letter = labels[predicted_class] if predicted_class < len(labels) else "Unknown"
except:
return "Prediction error", None
result_text = f"Prediction: {letter} (Confidence: {confidence:.2f})"
cv2.putText(frame_with_hands, result_text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
output_image = cv2.cvtColor(frame_with_hands, cv2.COLOR_BGR2RGB)
return result_text, Image.fromarray(output_image)
# Gradio interface
interface = gr.Interface(
fn=process_image,
inputs=gr.Image(label="Upload Hand Sign Image", type="pil"),
outputs=[
gr.Text(label="Prediction Result"),
gr.Image(label="Processed Image")
],
title="ASL Sign Language Recognition",
description="Upload an image of a hand sign to recognize the ASL letter."
)
if __name__ == "__main__":
interface.launch(share=True)