maftuh-main commited on
Commit
06761bb
·
1 Parent(s): 96e506d

Deploy MobileNetV2 model (95.43% accuracy, 160x160 input)

Browse files
Files changed (1) hide show
  1. app.py +36 -22
app.py CHANGED
@@ -1,6 +1,7 @@
1
  """
2
- Batik Classifier API - Keras Model
3
- Fine-tuned InceptionV3 with ~27% validation accuracy
 
4
  """
5
 
6
  import os
@@ -17,7 +18,7 @@ os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
17
 
18
  import tensorflow as tf
19
  from tensorflow import keras
20
- from tensorflow.keras.applications.inception_v3 import preprocess_input
21
 
22
  app = Flask(__name__)
23
  CORS(app)
@@ -28,38 +29,41 @@ class_names = None
28
  config = None
29
 
30
  def load_models():
31
- """Load Keras model and class names"""
32
  global model, class_names, config
33
 
34
  model_dir = "models"
35
 
36
  try:
37
- # Load Keras model with compile=False to avoid custom layer issues
38
  model_path = os.path.join(model_dir, "batik_model.keras")
39
  model = keras.models.load_model(model_path, compile=False)
40
 
41
- # Compile manually with simple config
42
  model.compile(
43
  optimizer='adam',
44
  loss='categorical_crossentropy',
45
  metrics=['accuracy']
46
  )
47
 
48
- print(f" Loaded Keras model from {model_path}")
49
- print(f" Model input shape: {model.input_shape}")
50
- print(f" Model output shape: {model.output_shape}")
 
51
 
52
  # Load class names
53
  classes_path = os.path.join(model_dir, "batik_classes.json")
54
  with open(classes_path, 'r') as f:
55
  class_names = json.load(f)
56
- print(f" Loaded {len(class_names)} classes")
57
 
58
  # Load config
59
  config_path = os.path.join(model_dir, "batik_config.json")
60
  with open(config_path, 'r') as f:
61
  config = json.load(f)
62
- print(f" Loaded config: {config}")
 
 
63
 
64
  return True
65
 
@@ -69,13 +73,14 @@ def load_models():
69
  traceback.print_exc()
70
  return False
71
 
72
- def preprocess_image(image, target_size=(299, 299)):
73
- """Preprocess image for InceptionV3"""
74
  if image.mode != 'RGB':
75
  image = image.convert('RGB')
76
 
77
- image = image.resize(target_size)
78
- img_array = np.array(image)
 
79
  img_array = np.expand_dims(img_array, axis=0)
80
  img_array = preprocess_input(img_array)
81
 
@@ -86,11 +91,13 @@ def index():
86
  """API info endpoint"""
87
  return jsonify({
88
  "name": "Batik Classifier API",
89
- "model": "Fine-tuned InceptionV3 (Keras)",
 
90
  "classes": len(class_names) if class_names else 0,
91
  "accuracy": config.get('val_accuracy', 0) if config else 0,
92
  "train_accuracy": config.get('train_accuracy', 0) if config else 0,
93
  "epochs": config.get('epochs', 0) if config else 0,
 
94
  "endpoints": {
95
  "/": "API info",
96
  "/predict": "POST - Classify batik image",
@@ -106,7 +113,8 @@ def health():
106
  return jsonify({
107
  "status": "healthy",
108
  "model_loaded": model is not None,
109
- "classes_loaded": class_names is not None
 
110
  })
111
 
112
  @app.route('/classes', methods=['GET'])
@@ -130,7 +138,7 @@ def get_info():
130
 
131
  @app.route('/predict', methods=['POST'])
132
  def predict():
133
- """Classify batik image"""
134
 
135
  if model is None or class_names is None:
136
  return jsonify({"error": "Model not loaded"}), 500
@@ -164,7 +172,8 @@ def predict():
164
  return jsonify({
165
  "predicted_class": predicted_class,
166
  "confidence": confidence,
167
- "top5_predictions": top5_predictions
 
168
  })
169
 
170
  except Exception as e:
@@ -175,14 +184,19 @@ def predict():
175
  }), 500
176
 
177
  # Load models on startup
178
- print("=" * 60)
179
- print("Loading Batik Classifier Models...")
180
- print("=" * 60)
181
 
182
  if load_models():
 
183
  print(" All models loaded successfully!")
 
 
184
  else:
 
185
  print(" Failed to load models")
 
186
 
187
  if __name__ == '__main__':
188
  app.run(host='0.0.0.0', port=7860)
 
1
  """
2
+ Batik Classifier API - MobileNetV2 Model
3
+ 95.43% accuracy on 42 batik classes
4
+ Efficient mobile/web deployment
5
  """
6
 
7
  import os
 
18
 
19
  import tensorflow as tf
20
  from tensorflow import keras
21
+ from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
22
 
23
  app = Flask(__name__)
24
  CORS(app)
 
29
  config = None
30
 
31
  def load_models():
32
+ """Load MobileNetV2 model and class names"""
33
  global model, class_names, config
34
 
35
  model_dir = "models"
36
 
37
  try:
38
+ # Load Keras model with compile=False to avoid compatibility issues
39
  model_path = os.path.join(model_dir, "batik_model.keras")
40
  model = keras.models.load_model(model_path, compile=False)
41
 
42
+ # Compile manually
43
  model.compile(
44
  optimizer='adam',
45
  loss='categorical_crossentropy',
46
  metrics=['accuracy']
47
  )
48
 
49
+ print(f" Loaded MobileNetV2 model from {model_path}")
50
+ print(f" Input shape: {model.input_shape}")
51
+ print(f" Output shape: {model.output_shape}")
52
+ print(f" Total params: {model.count_params():,}")
53
 
54
  # Load class names
55
  classes_path = os.path.join(model_dir, "batik_classes.json")
56
  with open(classes_path, 'r') as f:
57
  class_names = json.load(f)
58
+ print(f" Loaded {len(class_names)} batik classes")
59
 
60
  # Load config
61
  config_path = os.path.join(model_dir, "batik_config.json")
62
  with open(config_path, 'r') as f:
63
  config = json.load(f)
64
+ print(f" Model config: {config.get('model', 'Unknown')}")
65
+ print(f" Train accuracy: {config.get('train_accuracy', 0):.2%}")
66
+ print(f" Val accuracy: {config.get('val_accuracy', 0):.2%}")
67
 
68
  return True
69
 
 
73
  traceback.print_exc()
74
  return False
75
 
76
+ def preprocess_image(image, target_size=(160, 160)):
77
+ """Preprocess image for MobileNetV2 (160x160 input)"""
78
  if image.mode != 'RGB':
79
  image = image.convert('RGB')
80
 
81
+ # Resize to 160x160 (MobileNetV2 input size)
82
+ image = image.resize(target_size, Image.Resampling.LANCZOS)
83
+ img_array = np.array(image, dtype=np.float32)
84
  img_array = np.expand_dims(img_array, axis=0)
85
  img_array = preprocess_input(img_array)
86
 
 
91
  """API info endpoint"""
92
  return jsonify({
93
  "name": "Batik Classifier API",
94
+ "model": "MobileNetV2",
95
+ "description": "Efficient mobile/web batik classifier",
96
  "classes": len(class_names) if class_names else 0,
97
  "accuracy": config.get('val_accuracy', 0) if config else 0,
98
  "train_accuracy": config.get('train_accuracy', 0) if config else 0,
99
  "epochs": config.get('epochs', 0) if config else 0,
100
+ "input_size": "160x160",
101
  "endpoints": {
102
  "/": "API info",
103
  "/predict": "POST - Classify batik image",
 
113
  return jsonify({
114
  "status": "healthy",
115
  "model_loaded": model is not None,
116
+ "classes_loaded": class_names is not None,
117
+ "model_type": "MobileNetV2"
118
  })
119
 
120
  @app.route('/classes', methods=['GET'])
 
138
 
139
  @app.route('/predict', methods=['POST'])
140
  def predict():
141
+ """Classify batik image using MobileNetV2"""
142
 
143
  if model is None or class_names is None:
144
  return jsonify({"error": "Model not loaded"}), 500
 
172
  return jsonify({
173
  "predicted_class": predicted_class,
174
  "confidence": confidence,
175
+ "top5_predictions": top5_predictions,
176
+ "model": "MobileNetV2"
177
  })
178
 
179
  except Exception as e:
 
184
  }), 500
185
 
186
  # Load models on startup
187
+ print("=" * 70)
188
+ print(" Batik Classifier API - MobileNetV2")
189
+ print("=" * 70)
190
 
191
  if load_models():
192
+ print("=" * 70)
193
  print(" All models loaded successfully!")
194
+ print(" Ready to classify batik patterns")
195
+ print("=" * 70)
196
  else:
197
+ print("=" * 70)
198
  print(" Failed to load models")
199
+ print("=" * 70)
200
 
201
  if __name__ == '__main__':
202
  app.run(host='0.0.0.0', port=7860)