AtthalaricNero commited on
Commit ·
d5f00c3
1
Parent(s): d77c00f
Refactor preprocessing pipeline to include brightness normalization and streamline image processing
Browse files
app.py
CHANGED
|
@@ -41,6 +41,22 @@ CLASS_NAMES = [
|
|
| 41 |
"Salak",
|
| 42 |
]
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
def extract_color_histogram(img, bins=(8, 8, 8)):
|
| 45 |
hist = cv2.calcHist([img], [0, 1, 2], None, bins, [0, 256, 0, 256, 0, 256])
|
| 46 |
hist = cv2.normalize(hist, hist).flatten()
|
|
@@ -57,17 +73,10 @@ def extract_lbp_features(gray_img, P=8, R=1, method="uniform"):
|
|
| 57 |
|
| 58 |
|
| 59 |
def preprocessing_pipeline(pil_img):
|
| 60 |
-
"""
|
| 61 |
-
Pipeline preprocessing sesuai dengan data training:
|
| 62 |
-
- Convert ke RGB
|
| 63 |
-
- Resize ke 100x100
|
| 64 |
-
- Extract color histogram & LBP features
|
| 65 |
-
"""
|
| 66 |
-
# Convert ke RGB dan resize ke 100x100 (sesuai dataset training)
|
| 67 |
img = np.array(pil_img.convert('RGB'))
|
| 68 |
img = cv2.resize(img, (100, 100), interpolation=cv2.INTER_AREA)
|
| 69 |
|
| 70 |
-
img_float =
|
| 71 |
img_uint8 = (img_float * 255).astype(np.uint8)
|
| 72 |
|
| 73 |
feat_color = extract_color_histogram(img_uint8)
|
|
@@ -102,10 +111,8 @@ def index():
|
|
| 102 |
try:
|
| 103 |
image = Image.open(file.stream)
|
| 104 |
|
| 105 |
-
# Preprocessing sesuai dengan data training (hanya resize 100x100)
|
| 106 |
features = preprocessing_pipeline(image)
|
| 107 |
|
| 108 |
-
# Untuk tampilan, resize ke 100x100
|
| 109 |
preprocessed_img = cv2.resize(np.array(image.convert('RGB')), (100, 100), interpolation=cv2.INTER_AREA)
|
| 110 |
preprocessed_pil = Image.fromarray(preprocessed_img)
|
| 111 |
|
|
@@ -114,16 +121,13 @@ def index():
|
|
| 114 |
encoded_img = base64.b64encode(img_io.getvalue()).decode("ascii")
|
| 115 |
img_data = f"data:image/png;base64, {encoded_img}"
|
| 116 |
|
| 117 |
-
# Prediksi dengan probabilitas
|
| 118 |
pred_index = model.predict(features)[0]
|
| 119 |
prediction_text = CLASS_NAMES[int(pred_index)]
|
| 120 |
|
| 121 |
-
# Dapatkan probabilitas untuk semua kelas
|
| 122 |
if hasattr(model, 'predict_proba'):
|
| 123 |
probabilities = model.predict_proba(features)[0]
|
| 124 |
confidence = float(probabilities[int(pred_index)]) * 100
|
| 125 |
|
| 126 |
-
# Dapatkan top 3 prediksi
|
| 127 |
top_3_indices = probabilities.argsort()[-3:][::-1]
|
| 128 |
top_3_predictions = [
|
| 129 |
{
|
|
@@ -133,7 +137,6 @@ def index():
|
|
| 133 |
for idx in top_3_indices
|
| 134 |
]
|
| 135 |
else:
|
| 136 |
-
# Jika model tidak support predict_proba
|
| 137 |
confidence = None
|
| 138 |
top_3_predictions = None
|
| 139 |
|
|
|
|
| 41 |
"Salak",
|
| 42 |
]
|
| 43 |
|
| 44 |
+
def normalize_brightness(img):
|
| 45 |
+
"""Normalisasi brightness dan contrast untuk konsistensi"""
|
| 46 |
+
# Convert ke LAB color space
|
| 47 |
+
lab = cv2.cvtColor(img, cv2.COLOR_RGB2LAB)
|
| 48 |
+
l, a, b = cv2.split(lab)
|
| 49 |
+
|
| 50 |
+
# Apply CLAHE (Contrast Limited Adaptive Histogram Equalization) pada channel L
|
| 51 |
+
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
|
| 52 |
+
l = clahe.apply(l)
|
| 53 |
+
|
| 54 |
+
# Merge kembali
|
| 55 |
+
lab = cv2.merge([l, a, b])
|
| 56 |
+
normalized = cv2.cvtColor(lab, cv2.COLOR_LAB2RGB)
|
| 57 |
+
|
| 58 |
+
return normalized
|
| 59 |
+
|
| 60 |
def extract_color_histogram(img, bins=(8, 8, 8)):
|
| 61 |
hist = cv2.calcHist([img], [0, 1, 2], None, bins, [0, 256, 0, 256, 0, 256])
|
| 62 |
hist = cv2.normalize(hist, hist).flatten()
|
|
|
|
| 73 |
|
| 74 |
|
| 75 |
def preprocessing_pipeline(pil_img):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
img = np.array(pil_img.convert('RGB'))
|
| 77 |
img = cv2.resize(img, (100, 100), interpolation=cv2.INTER_AREA)
|
| 78 |
|
| 79 |
+
img_float = normalize_brightness(img)
|
| 80 |
img_uint8 = (img_float * 255).astype(np.uint8)
|
| 81 |
|
| 82 |
feat_color = extract_color_histogram(img_uint8)
|
|
|
|
| 111 |
try:
|
| 112 |
image = Image.open(file.stream)
|
| 113 |
|
|
|
|
| 114 |
features = preprocessing_pipeline(image)
|
| 115 |
|
|
|
|
| 116 |
preprocessed_img = cv2.resize(np.array(image.convert('RGB')), (100, 100), interpolation=cv2.INTER_AREA)
|
| 117 |
preprocessed_pil = Image.fromarray(preprocessed_img)
|
| 118 |
|
|
|
|
| 121 |
encoded_img = base64.b64encode(img_io.getvalue()).decode("ascii")
|
| 122 |
img_data = f"data:image/png;base64, {encoded_img}"
|
| 123 |
|
|
|
|
| 124 |
pred_index = model.predict(features)[0]
|
| 125 |
prediction_text = CLASS_NAMES[int(pred_index)]
|
| 126 |
|
|
|
|
| 127 |
if hasattr(model, 'predict_proba'):
|
| 128 |
probabilities = model.predict_proba(features)[0]
|
| 129 |
confidence = float(probabilities[int(pred_index)]) * 100
|
| 130 |
|
|
|
|
| 131 |
top_3_indices = probabilities.argsort()[-3:][::-1]
|
| 132 |
top_3_predictions = [
|
| 133 |
{
|
|
|
|
| 137 |
for idx in top_3_indices
|
| 138 |
]
|
| 139 |
else:
|
|
|
|
| 140 |
confidence = None
|
| 141 |
top_3_predictions = None
|
| 142 |
|