Spaces:
Sleeping
Sleeping
File size: 6,517 Bytes
d9549b5 401fbaa 549673d 401fbaa 549673d 401fbaa 549673d 401fbaa 549673d b1a3f7b 401fbaa b1a3f7b 401fbaa 549673d 401fbaa b1a3f7b 192f079 b1a3f7b 8a57d93 b1a3f7b 8a57d93 549673d 8a57d93 549673d 8a57d93 549673d 8a57d93 b1a3f7b 8a57d93 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | # inference.py
import tensorflow as tf
import logging
from preprocessing import VideoPreprocessor
# Configure Logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class LipReadingModel:
def __init__(self, model_path='best_model_1_WER.keras'):
# Initialize character mappings before loading the model
vocab = [x for x in "aăâbcdđeêghiklmnoôơpqrstuưvxyáàảãạấầẩẫậắằẳẵặéèẻẽẹếềểễệíìỉĩịóòỏõọốồổỗộớờởỡợúùủũụứừửữựýỳỷỹỵ'?!123456789 "]
self.char_to_num = tf.keras.layers.StringLookup(vocabulary=vocab, oov_token="")
self.num_to_char = tf.keras.layers.StringLookup(
vocabulary=self.char_to_num.get_vocabulary(), oov_token="", invert=True
)
try:
self.model = tf.keras.models.load_model(
model_path,
custom_objects={'CTCLoss': self.CTCLoss} # Include custom loss if needed
)
logger.info("Model loaded successfully.")
except Exception as e:
logger.error(f"Error loading model: {e}")
self.model = self.build_model() # Fallback to building the model if loading fails
@staticmethod
def CTCLoss(y_true, y_pred):
batch_len = tf.cast(tf.shape(y_true)[0], dtype="int64")
input_length = tf.cast(tf.shape(y_pred)[1], dtype="int64")
label_length = tf.cast(tf.shape(y_true)[1], dtype="int64")
input_length = input_length * tf.ones(shape=(batch_len, 1), dtype="int64")
label_length = label_length * tf.ones(shape=(batch_len, 1), dtype="int64")
return tf.keras.backend.ctc_batch_cost(y_true, y_pred, input_length, label_length)
def build_model(self):
model = tf.keras.Sequential()
# First convolutional layer with BatchNormalization
model.add(tf.keras.layers.Conv3D(64, (3, 3, 3), strides=(1, 2, 2), input_shape=(None, 85, 85, 1), padding='same'))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Activation('relu'))
model.add(tf.keras.layers.MaxPool3D((1, 2, 2), padding='same'))
# Second convolutional layer
model.add(tf.keras.layers.Conv3D(128, (3, 3, 3), strides=(1, 2, 2), padding='same'))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Activation('relu'))
model.add(tf.keras.layers.MaxPool3D((1, 2, 2), padding='same'))
# Third convolutional layer
model.add(tf.keras.layers.Conv3D(256, (3, 3, 3), strides=(1, 2, 2), padding='same'))
model.add(tf.keras.layers.LayerNormalization())
model.add(tf.keras.layers.Activation('relu'))
model.add(tf.keras.layers.MaxPool3D((1, 2, 2), padding='same'))
# Fourth convolutional layer
model.add(tf.keras.layers.Conv3D(256, (3, 3, 3), padding='same'))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Activation('relu'))
model.add(tf.keras.layers.MaxPool3D((1, 2, 2), padding='same'))
# Flatten and pass through TimeDistributed
model.add(tf.keras.layers.TimeDistributed(tf.keras.layers.Flatten()))
# Bidirectional LSTM layers
model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(512, kernel_initializer='Orthogonal', return_sequences=True)))
model.add(tf.keras.layers.Dropout(0.4))
model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(256, kernel_initializer='Orthogonal', return_sequences=True)))
model.add(tf.keras.layers.Dropout(0.4))
# Final dense layer
model.add(tf.keras.layers.Dense(self.char_to_num.vocabulary_size() + 1, kernel_initializer='he_normal', activation='softmax'))
logger.info("Built the model architecture successfully.")
return model
def predict(self, normalized_frames):
if self.model is None:
return "❌ Model not loaded. Please check the model path and ensure the model file is accessible."
if normalized_frames is None or int(tf.size(normalized_frames)) == 0:
return "❌ No frames extracted from the video. Please ensure the video contains a clear view of the face and lips."
try:
# Add batch dimension
frames = tf.expand_dims(normalized_frames, axis=0) # Shape: (1, num_frames, 85, 85, 1)
# Perform prediction
yhat = self.model.predict(frames, verbose=0)
input_length = [yhat.shape[1]] # batch size of 1
# Perform CTC decoding
decoded_tf = tf.keras.backend.ctc_decode(yhat, input_length=input_length, greedy=True)[0][0]
decoded = decoded_tf.numpy().flatten() # Convert to numpy array and flatten
logger.debug(f"Decoded prediction: {decoded}")
# Convert numerical predictions to characters
prediction = ''.join(
[
self.num_to_char(int(num)).numpy().decode('utf-8')
for num in decoded
if int(num) != -1
]
)
return prediction
except Exception as e:
logger.error(f"Error during prediction: {e}")
return f"❌ An error occurred during prediction: {e}"
def predict_from_video(video_path=None, frames=None, model=None, preprocessor=None):
"""
Predicts the text from a video file or webcam frames using the provided model.
Args:
video_path (str, optional): Path to the video file. Defaults to None.
frames (List[np.ndarray], optional): List of frames from webcam. Defaults to None.
model (LipReadingModel, optional): An instance of the LipReadingModel. Defaults to None.
preprocessor (VideoPreprocessor, optional): An instance of the VideoPreprocessor. Defaults to None.
Returns:
str: Predicted text.
"""
if model is None:
model = LipReadingModel()
if preprocessor is None:
preprocessor = VideoPreprocessor()
if video_path:
# Preprocess video from file
normalized_frames = preprocessor.preprocess_video(video_path)
elif frames is not None:
# Preprocess frames from webcam
normalized_frames = preprocessor.preprocess_frames(frames)
else:
return "❌ No video or frames provided for prediction."
prediction = model.predict(normalized_frames)
return prediction
|