File size: 2,746 Bytes
faa7b1a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# model_utils.py
import tensorflow as tf
import numpy as np
from PIL import Image
import streamlit as st
import os
import logging

# Get logger from config or main app
logger = logging.getLogger('bloodcell_app') # Assumes logger is configured in app.py

@st.cache_resource # Caching is crucial for performance
def load_tf_model(model_path):
    """Loads a TensorFlow/Keras model, handling potential errors."""
    if not os.path.exists(model_path):
        logger.error(f"Model file not found at path: {model_path}")
        st.error(f"Model file not found: {os.path.basename(model_path)}. Please ensure it's in the correct directory.")
        return None
    try:
        logger.info(f"Loading TensorFlow model from {model_path}...")
        model = tf.keras.models.load_model(model_path)
        logger.info(f"Model {os.path.basename(model_path)} loaded successfully.")
        return model
    except Exception as e:
        logger.error(f"Error loading TensorFlow model from {model_path}: {e}")
        st.error(f"Error loading model {os.path.basename(model_path)}: {e}")
        return None

def preprocess_and_predict(image: Image.Image, model: tf.keras.Model, class_names: list, target_size: tuple):
    """Preprocess image and predict class using the provided model."""
    if model is None:
        st.error("Prediction model is not loaded.")
        return None, None

    try:
        # Resize and ensure RGB
        img_resized = image.resize(target_size)
        if img_resized.mode != 'RGB':
            img_resized = img_resized.convert('RGB')

        # Normalize and add batch dimension
        img_array = np.array(img_resized) / 255.0
        img_array = np.expand_dims(img_array, axis=0) # Shape: (1, height, width, 3)

        # Predict
        predictions = model.predict(img_array) # Shape: (1, num_classes)

        # Get predicted class and confidence
        pred_index = np.argmax(predictions, axis=1)[0]
        if pred_index < len(class_names):
            predicted_class = class_names[pred_index]
            confidence = np.max(predictions) * 100
            logger.info(f"Prediction: {predicted_class} with {confidence:.2f}% confidence.")
            return predicted_class, confidence
        else:
            logger.error(f"Prediction index {pred_index} is out of bounds for class_names list (length {len(class_names)}).")
            st.error("Model prediction resulted in an invalid class index. Check model compatibility.")
            return None, None

    except Exception as e:
        logger.error(f"Error during image preprocessing or prediction: {e}")
        st.error(f"Image processing/prediction error: {e}")
        return None, None