200 lines
5.6 KiB
Python
200 lines
5.6 KiB
Python
import cv2
|
|
import numpy as np
|
|
import tensorflow as tf
|
|
|
|
anchor_grid = np.array([
|
|
[ 7.34375, 7.96875],
|
|
[ 6.65625, 10.46875],
|
|
[ 9.28125, 10.40625],
|
|
[ 5.34375, 9.21875],
|
|
[10.28125, 6.65625]
|
|
])
|
|
|
|
min_max_delta_xy = (-0.1, 0.1)
|
|
min_max_delta_wh = (-1.21, 1.21)
|
|
|
|
def getCoordinate(x, y, w, h):
|
|
w_half = w // 2
|
|
h_half = h // 2
|
|
|
|
x1 = int(x - w_half)
|
|
y1 = int(y - h_half)
|
|
x2 = int(x + w_half)
|
|
y2 = int(y + h_half)
|
|
|
|
return x1, y1, x2, y2
|
|
|
|
def getBoxSize(x1, y1, x2, y2):
|
|
w = x2 - x1
|
|
h = y2 - y1
|
|
|
|
return w, h
|
|
|
|
def getScale(currentSize, targetSize):
|
|
w, h = currentSize
|
|
w1, h1 = targetSize
|
|
|
|
scale_w = w1 / w
|
|
scale_h = h1 / h
|
|
|
|
return scale_w, scale_h
|
|
|
|
def getGridIndex(xc, xy):
|
|
cx = xc // 32
|
|
cy = xy // 32
|
|
|
|
return cx, cy
|
|
|
|
def convToGridCoord(xc, yc, cx, cy):
|
|
xg = (xc - (cx * 32)) / 32
|
|
yg = (yc - (cy * 32)) / 32
|
|
|
|
return xg, yg
|
|
|
|
def convToGridSize(w, h):
|
|
wg = w / 32
|
|
hg = h / 32
|
|
|
|
return wg, hg
|
|
|
|
def convToImageCoord(xg, yg, cx, cy):
|
|
x = int(round(32 * xg + 32 * cx))
|
|
y = int(round(32 * yg + 32 * cy))
|
|
|
|
return x, y
|
|
|
|
def convToImageSize(wg, hg):
|
|
w_img = int(round(wg * 32))
|
|
h_img = int(round(hg * 32))
|
|
|
|
return w_img, h_img
|
|
|
|
import math
|
|
|
|
def getDelta(xg, yg, wg, hg, w_anchorGrid, h_anchorGrid):
|
|
delta_x = (xg - 0.5) / w_anchorGrid
|
|
delta_y = (yg - 0.5) / h_anchorGrid
|
|
delta_w = math.log(wg / w_anchorGrid)
|
|
delta_h = math.log(hg / h_anchorGrid)
|
|
|
|
return delta_x, delta_y, delta_w, delta_h
|
|
|
|
def convDeltaCoord(delta_x, delta_y, w_anchorGrid, h_anchorGrid, cx, cy):
|
|
xg = delta_x * w_anchorGrid + 0.5
|
|
yg = delta_y * h_anchorGrid + 0.5
|
|
|
|
x, y = convToImageCoord(xg, yg, cx, cy)
|
|
|
|
return x, y
|
|
|
|
def convDeltaSize(delta_w, delta_h, w_anchorGrid, h_anchorGrid):
|
|
wg = w_anchorGrid * np.exp(delta_w)
|
|
hg = h_anchorGrid * np.exp(delta_h)
|
|
|
|
w, h = convToImageSize(wg, hg)
|
|
|
|
return w, h
|
|
|
|
#normalize = membuat nilai delta dalam rentang 0 hingga 1
|
|
def normalize_delta(val, min_val, max_val):
|
|
return (val - min_val) / (max_val - min_val)
|
|
|
|
#denormalize = mengembalikan nilai delta yang telah dinormalisasi ke nilai aslinya
|
|
def denormalize_delta(val, min_val, max_val):
|
|
return val * (max_val - min_val) + min_val
|
|
|
|
def showPredictionResult(image, y_pred, ground_truth = None, threshold = 0.5):
|
|
img = np.copy(image)
|
|
class_pred = 0 # Anggap t[5:] adalah skor untuk setiap kelas
|
|
|
|
for i in range(13):
|
|
for j in range(13):
|
|
for b in range(5):
|
|
cur_y_pred = y_pred[i, j, b]
|
|
|
|
conf = cur_y_pred[0]
|
|
|
|
if conf < threshold:
|
|
continue
|
|
|
|
colors = [
|
|
(1, 0, 0), # red
|
|
(0, 1, 0), # green
|
|
(1, 1, 0) # yellow
|
|
]
|
|
|
|
delta_x = denormalize_delta(cur_y_pred[1], *min_max_delta_xy) # denormalize delta_x
|
|
delta_y = denormalize_delta(cur_y_pred[2], *min_max_delta_xy) # denormalize delta_y
|
|
delta_w = denormalize_delta(cur_y_pred[3], *min_max_delta_wh) # denormalize delta_w
|
|
delta_h = denormalize_delta(cur_y_pred[4], *min_max_delta_wh) # denormalize delta_h
|
|
|
|
x, y = convDeltaCoord(delta_x, delta_y, *anchor_grid[b], i, j)
|
|
w, h = convDeltaSize(delta_w, delta_h, *anchor_grid[b])
|
|
|
|
x1, y1, x2, y2 = getCoordinate(x, y, w, h)
|
|
|
|
|
|
|
|
class_pred = np.argmax(cur_y_pred[5:]) # Anggap t[5:] adalah skor untuk setiap kelas
|
|
|
|
# Menggambar kotak latar belakang untuk teks
|
|
text_size, _ = cv2.getTextSize(chr(65 + class_pred), cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
|
|
cv2.rectangle(img, (x1, y1 - text_size[1] - 5), (x1 + text_size[0] + 5, y1), (1, 1, 1), -1)
|
|
|
|
# Menambahkan teks dari class prediksi
|
|
class_text = chr(65 + class_pred) # Mengubah indeks kelas menjadi huruf kapital
|
|
cv2.putText(img, class_text, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
|
|
|
|
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 1, 0), 2)
|
|
|
|
if ground_truth is not None:
|
|
cur_gt = ground_truth[i, j, b]
|
|
|
|
gt_delta_x = denormalize_delta(cur_gt[1], *min_max_delta_xy) # denormalize delta_x
|
|
gt_delta_y = denormalize_delta(cur_gt[2], *min_max_delta_xy) # denormalize delta_y
|
|
gt_delta_w = denormalize_delta(cur_gt[3], *min_max_delta_wh) # denormalize delta_w
|
|
gt_delta_h = denormalize_delta(cur_gt[4], *min_max_delta_wh) # denormalize delta_h
|
|
|
|
gt_x, gt_y = convDeltaCoord(gt_delta_x, gt_delta_y, *anchor_grid[b], i, j)
|
|
gt_w, gt_h = convDeltaSize(gt_delta_w, gt_delta_h, *anchor_grid[b])
|
|
|
|
gt_x1, gt_y1, gt_x2, gt_y2 = getCoordinate(gt_x, gt_y, gt_w, gt_h)
|
|
|
|
cv2.rectangle(img, (gt_x1, gt_y1), (gt_x2, gt_y2), (1, 0, 0.95), 1)
|
|
|
|
return img, class_pred
|
|
|
|
def predictImage(model, image, threshold = 0.5):
|
|
img = np.copy(image)
|
|
|
|
img = cv2.resize(img, (416, 416))
|
|
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
|
img = img / 255
|
|
img = tf.expand_dims(img, axis = 0)
|
|
|
|
y_pred = model.predict(img)
|
|
|
|
max_conf = tf.reduce_max(y_pred[..., 0], keepdims = True)
|
|
|
|
|
|
img, class_pred = showPredictionResult(img[0].numpy(), y_pred[0], threshold = max_conf)
|
|
img = (img * 255).astype(np.uint8)
|
|
|
|
return img, class_pred
|
|
|
|
def generate_html(predictions):
|
|
predictions_str = ''.join(predictions)
|
|
html_content = f'''
|
|
<html>
|
|
<head>
|
|
<title>Hasil Prediksi</title>
|
|
</head>
|
|
<body>
|
|
<h1>Huruf yang Diprediksi</h1>
|
|
<p>{predictions_str}</p>
|
|
</body>
|
|
</html>
|
|
'''
|
|
|
|
return html_content
|