File size: 5,257 Bytes
a1af663
 
 
da8478b
a1af663
 
fa3799f
 
 
 
bd36261
 
 
a1af663
 
 
 
 
d84d114
 
a1af663
a786b7a
 
1e1e4e2
 
 
 
a786b7a
fa3799f
a786b7a
1e1e4e2
fa3799f
d36ee05
 
5e5b44c
a1af663
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
da8478b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a1af663
 
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import os
import cv2
import numpy as np
import base64
from flask import Flask, request, render_template, jsonify
from werkzeug.utils import secure_filename

# Suppress TensorFlow warnings
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

# Use TensorFlow 2.0 integrated Keras
import tensorflow as tf
from tensorflow.keras.models import load_model

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB max file size
app.config['UPLOAD_FOLDER'] = 'uploads'

# Create uploads folder if it doesn't exist with proper permissions
os.makedirs(app.config['UPLOAD_FOLDER'], mode=0o777, exist_ok=True)

# Load the model with TensorFlow 2.16 (Keras 3)
print("Loading model with TensorFlow 2.16 (Keras 3)...")
import warnings
warnings.filterwarnings('ignore')

try:
    # TensorFlow 2.16+ uses Keras 3 which handles the model format
    model = load_model('cancer_model.h5', compile=False)
    print("✓ Model loaded successfully with Keras 3!")
except Exception as e:
    print(f"❌ Error loading model: {e}")
    import traceback
    traceback.print_exc()
    raise

def resize_with_padding(img, target_size):
    """Resize image while maintaining aspect ratio and add padding"""
    height, width = img.shape[:2]
    target_width, target_height = target_size
    
    # Calculate scaling factor
    scale = min(target_width / width, target_height / height)
    new_width = int(width * scale)
    new_height = int(height * scale)
    
    # Resize image
    resized_image = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_AREA)
    
    # Calculate padding
    pad_width = target_width - new_width
    pad_height = target_height - new_height
    top = pad_height // 2
    bottom = pad_height - top
    left = pad_width // 2
    right = pad_width - left
    
    # Add black padding
    padded_image = cv2.copyMakeBorder(resized_image, top, bottom, left, right, 
                                     cv2.BORDER_CONSTANT, value=[0, 0, 0])
    return padded_image

def left_or_right(img):
    """Normalize left/right breast orientation"""
    height, width = img.shape[:2]
    left_half = img[:, :width // 2]
    right_half = img[:, width // 2:]
    left_intensity = np.sum(left_half)
    right_intensity = np.sum(right_half)
    return img if left_intensity > right_intensity else cv2.flip(img, 1)

def predict_image(image_path):
    """Make prediction on uploaded image"""
    # Read image
    img = cv2.imread(image_path)
    
    # Preprocess
    img = resize_with_padding(img, (256, 256))
    img = left_or_right(img)
    img = img / 255.0
    img = np.expand_dims(img, axis=0)
    
    # Predict
    prediction_prob = model.predict(img, verbose=0)
    predicted_class = 1 if prediction_prob[0][0] > 0.5 else 0
    confidence = float(prediction_prob[0][0] if predicted_class == 1 else 1 - prediction_prob[0][0])
    
    result = {
        'class': 'Malignant' if predicted_class == 1 else 'Benign',
        'confidence': confidence * 100,
        'malignant_prob': float(prediction_prob[0][0]) * 100,
        'benign_prob': (1 - float(prediction_prob[0][0])) * 100
    }
    
    return result

@app.route('/')
def index():
    """Render main page"""
    return render_template('index.html')

@app.route('/predict', methods=['POST'])
def predict():
    """Handle prediction request"""
    if 'file' not in request.files:
        return jsonify({'error': 'No file uploaded'}), 400
    
    file = request.files['file']
    
    if file.filename == '':
        return jsonify({'error': 'No file selected'}), 400
    
    if file:
        # Save uploaded file
        filename = secure_filename(file.filename)
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(filepath)
        
        try:
            # Make prediction
            result = predict_image(filepath)
            
            # Clean up
            os.remove(filepath)
            
            return jsonify(result)
        except Exception as e:
            if os.path.exists(filepath):
                os.remove(filepath)
            return jsonify({'error': str(e)}), 500

@app.route('/test-example', methods=['POST'])
def test_example():
    """Test with example image"""
    try:
        example_path = 'image/20251012_13h56m44s_grim.png'
        
        if not os.path.exists(example_path):
            return jsonify({'error': 'Example image not found. Please add 20251012_13h56m44s_grim.png to image/ folder'}), 404
        
        print(f"Testing with example file: {example_path}")
        
        # Make prediction
        result = predict_image(example_path)
        
        # Read and encode image as base64
        with open(example_path, 'rb') as f:
            img_data = f.read()
        img_base64 = base64.b64encode(img_data).decode('utf-8')
        result['image'] = f"data:image/png;base64,{img_base64}"
        
        print(f"✓ Example prediction completed: {result['class']}")
        
        return jsonify(result)
        
    except Exception as e:
        print(f"Error during example prediction: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=7860, debug=False)