139 lines
5.1 KiB
Python
139 lines
5.1 KiB
Python
from flask import Flask, request, jsonify
|
|
import joblib
|
|
import cv2
|
|
import numpy as np
|
|
from werkzeug.utils import secure_filename
|
|
from skimage.measure import regionprops, label
|
|
import os
|
|
|
|
app = Flask(__name__)
|
|
app.config['UPLOAD_FOLDER'] = 'uploads/'
|
|
|
|
# Fungsi untuk menghitung eccentricity
|
|
def calculate_eccentricity(region):
|
|
if region.minor_axis_length == 0:
|
|
return 0
|
|
else:
|
|
return np.sqrt(1 - (region.minor_axis_length / region.major_axis_length)**2)
|
|
|
|
# Load model dan LabelEncoder yang telah disimpan
|
|
model_path = 'D:/Skripsi/ekstraksi fitur/rf_model.joblib'
|
|
label_encoder_path = 'D:/Skripsi/ekstraksi fitur/label_encoder.joblib'
|
|
rf_model = joblib.load(model_path)
|
|
le = joblib.load(label_encoder_path)
|
|
|
|
# Fungsi untuk mengekstraksi fitur dari gambar tunggal
|
|
def extract_features(image_path, label_name):
|
|
img = cv2.imread(image_path, 1)
|
|
if img is None:
|
|
print(f"Gagal membaca file: {image_path}")
|
|
return None
|
|
|
|
blue, green, red = cv2.split(img)
|
|
|
|
# Thresholding
|
|
if label_name == 'Corynebacterium Diphteriae':
|
|
ret, img_bin = cv2.threshold(green, 115, 255, cv2.THRESH_BINARY_INV)
|
|
img_bin = cv2.erode(cv2.dilate(img_bin, None, iterations=1), None, iterations=4)
|
|
elif label_name == 'Mycobacterium Tuberculosis':
|
|
ret, img_bin = cv2.threshold(green, 135, 255, cv2.THRESH_BINARY_INV)
|
|
img_bin = cv2.dilate(img_bin, None, iterations=1)
|
|
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(img_bin, connectivity=8)
|
|
mask = np.zeros_like(img_bin)
|
|
min_size = 50
|
|
max_size = 400
|
|
for j in range(1, num_labels):
|
|
if min_size <= stats[j, cv2.CC_STAT_AREA] <= max_size:
|
|
mask[labels == j] = 255
|
|
img_bin = mask
|
|
elif label_name == 'Neiseria Gonorroea':
|
|
ret, img_bin = cv2.threshold(green, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
|
|
img_bin = cv2.dilate(img_bin, None, iterations=1)
|
|
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(img_bin, connectivity=8)
|
|
mask = np.zeros_like(img_bin)
|
|
min_size = 200
|
|
max_size = 2500
|
|
for j in range(1, num_labels):
|
|
if min_size <= stats[j, cv2.CC_STAT_AREA] <= max_size:
|
|
mask[labels == j] = 255
|
|
img_bin = mask
|
|
elif label_name == 'Staphylococcus Aureus':
|
|
ret, img1 = cv2.threshold(green, 110, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
|
|
img_bin = cv2.erode(cv2.dilate(img1.copy(), None, iterations=1), None, iterations=1)
|
|
img_bin = cv2.morphologyEx(img_bin.copy(), cv2.MORPH_OPEN, None)
|
|
elif label_name == 'Streptococcus Pneumoniae':
|
|
ret, img1 = cv2.threshold(green, 110, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
|
|
img_bin = cv2.erode(img1.copy(), None, iterations=1)
|
|
img_bin = cv2.dilate(img1.copy(), None, iterations=1)
|
|
|
|
# Labeling
|
|
labeled_img = label(img_bin)
|
|
regions = regionprops(labeled_img)
|
|
num_objects = len(regions)
|
|
|
|
if num_objects == 0:
|
|
return None
|
|
|
|
# Inisialisasi variabel untuk agregasi
|
|
total_eccentricity = 0
|
|
total_metric = 0
|
|
total_area = 0
|
|
total_perimeter = 0
|
|
|
|
for region in regions:
|
|
eccentricity = calculate_eccentricity(region)
|
|
area = region.area
|
|
perimeter = region.perimeter
|
|
metric = (4 * np.pi * area) / (perimeter ** 2) if perimeter != 0 else 0
|
|
|
|
total_eccentricity += eccentricity
|
|
total_metric += metric
|
|
total_area += area
|
|
total_perimeter += perimeter
|
|
|
|
mean_eccentricity = total_eccentricity / num_objects
|
|
mean_metric = total_metric / num_objects
|
|
|
|
features = np.array([[num_objects, mean_eccentricity, mean_metric, total_area, total_perimeter]])
|
|
|
|
return features, {
|
|
'num_objects': num_objects,
|
|
'mean_eccentricity': mean_eccentricity,
|
|
'mean_metric': mean_metric,
|
|
'total_area': total_area,
|
|
'total_perimeter': total_perimeter
|
|
}
|
|
|
|
@app.route('/predict', methods=['POST'])
|
|
def upload_file():
|
|
if 'file' not in request.files:
|
|
return jsonify({'error': 'No file part'}), 400
|
|
file = request.files['file']
|
|
if file.filename == '':
|
|
return jsonify({'error': 'No selected file'}), 400
|
|
if file and allowed_file(file.filename):
|
|
filename = secure_filename(file.filename)
|
|
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
|
file.save(filepath)
|
|
|
|
label_name = request.form['label']
|
|
features, feature_details = extract_features(filepath, label_name)
|
|
|
|
if features is None:
|
|
return jsonify({'error': 'No objects found in the image'}), 400
|
|
|
|
y_pred = rf_model.predict(features)
|
|
label_pred = le.inverse_transform(y_pred)
|
|
|
|
return jsonify({
|
|
'prediction': label_pred[0],
|
|
'features': feature_details
|
|
})
|
|
return jsonify({'error': 'File type not allowed'}), 400
|
|
|
|
def allowed_file(filename):
|
|
return '.' in filename and filename.rsplit('.', 1)[1].lower() in {'png', 'jpg', 'jpeg'}
|
|
|
|
if __name__ == '__main__':
|
|
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
|
|
app.run(debug=True) |