Skip to content

Commit b496d44

Browse files
committed
Remove sklearn dependency
1 parent b7d68c7 commit b496d44

5 files changed

Lines changed: 51 additions & 30 deletions

File tree

abraia/demo.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@
1818
'model': 'multiple/tomato/yolov8n_v6.onnx',
1919
'src': '10179855-hd_1280_720_30fps.mp4',
2020
'labels': ['tomato'],
21-
'counter': [(960, 0), (960, 720)],
22-
'dest': 'tomato_onnx.mp4'
21+
'counter': [(960, 0), (960, 720)]
2322
},
2423
'apple': {
2524
'model': 'multiple/models/yolov8n-seg.onnx',
2625
'src': '5479199-hd_1280_720_25fps.mp4',
2726
'labels': ['apple'],
28-
'dest': 'apple_onnx.mp4'
27+
'counter': [(960, 0), (960, 720)]
2928
},
3029
'strawberry': {
3130
'model': 'multiple/strawberry/yolov8n.onnx',
@@ -61,14 +60,12 @@
6160
HAILO_DEMOS = {
6261
'tomato': {
6362
'hef_path': 'multiple/tomato/yolov8n.hef',
64-
'src': '10179855-hd_1280_720_30fps.mp4',
65-
'dest': 'tomato_hef.mp4'
63+
'src': '10179855-hd_1280_720_30fps.mp4'
6664
},
6765
'apple': {
6866
'hef_path': 'yolov5m_seg_with_nms',
6967
'task': 'segment',
70-
'src': '5479199-hd_1280_720_25fps.mp4',
71-
'dest': 'apple_hef.mp4'
68+
'src': '5479199-hd_1280_720_25fps.mp4'
7269
},
7370
'segment': {
7471
'hef_path': 'yolov5m_seg_with_nms',

abraia/multiple/__init__.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@ def save_image(src, img):
6060

6161
def principal_components(img, n_components=3, spectrum=False):
6262
"""Calculate principal components of the image"""
63-
from sklearn.decomposition import PCA
6463
h, w, d = img.shape
6564
X = img.reshape((h * w), d)
66-
pca = PCA(n_components=n_components, whiten=True)
67-
bands = np.squeeze(pca.fit_transform(X).reshape(h, w, n_components))
65+
X_mean = np.mean(X, axis=0)
66+
X_centered = X - X_mean
67+
U, S, Vt = np.linalg.svd(X_centered, full_matrices=False)
68+
# Transformed data with whitening
69+
bands = (U[:, :n_components] * np.sqrt(X.shape[0] - 1)).reshape(h, w, n_components)
6870
if spectrum:
69-
return bands, pca.components_
70-
return bands
71+
return np.squeeze(bands), Vt[:n_components, :]
72+
return np.squeeze(bands)
7173

7274

7375
def normalize(img):
@@ -108,7 +110,7 @@ def resize(img, size):
108110

109111
def resample(img, n_samples=32):
110112
"""Resample the number of spectral bands (n_samples)"""
111-
from sklearn.utils import resample
113+
from ..training.ops import resample
112114
h, w, d = img.shape
113115
X = img.reshape((h * w), d)
114116
r = resample(np.transpose(X), n_samples=n_samples)

abraia/multiple/hsi.py

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55

66
from PIL import Image
77

8-
from sklearn.svm import SVC
9-
from sklearn.model_selection import train_test_split
10-
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
8+
from ..training.ops import train_test_split
119

1210
from tensorflow import keras
1311
from keras.utils import np_utils
@@ -19,6 +17,36 @@
1917
multiple = Multiple()
2018

2119

20+
def accuracy_score(y_true, y_pred):
21+
return np.mean(y_true == y_pred)
22+
23+
24+
def confusion_matrix(y_true, y_pred):
25+
labels = np.unique(np.concatenate((y_true, y_pred)))
26+
n_labels = len(labels)
27+
cm = np.zeros((n_labels, n_labels), dtype=int)
28+
label_to_idx = {label: i for i, label in enumerate(labels)}
29+
for t, p in zip(y_true, y_pred):
30+
cm[label_to_idx[t], label_to_idx[p]] += 1
31+
return cm
32+
33+
34+
def classification_report(y_true, y_pred, target_names=None):
35+
cm = confusion_matrix(y_true, y_pred)
36+
precision = np.diag(cm) / np.sum(cm, axis=0)
37+
recall = np.diag(cm) / np.sum(cm, axis=1)
38+
f1 = 2 * (precision * recall) / (precision + recall)
39+
support = np.sum(cm, axis=1)
40+
41+
report = " precision recall f1-score support\n\n"
42+
for i, (p, r, f, s) in enumerate(zip(precision, recall, f1, support)):
43+
name = target_names[i] if target_names and i < len(target_names) else str(i)
44+
report += f"{name:>12} {p:.2f} {r:.2f} {f:.2f} {s:>7}\n"
45+
46+
report += f"\n accuracy {accuracy_score(y_true, y_pred):.2f} {np.sum(support):>7}\n"
47+
return report
48+
49+
2250
def load_dataset(dataset, shuffle=False):
2351
"""Load one of the available hyperspectral datasets (IP, PU, SA)."""
2452
paths, labels = [], []
@@ -220,31 +248,25 @@ def plot_train_history(history):
220248
class HyperspectralModel:
221249
def __init__(self, name, *args):
222250
self.name = name
223-
if self.name == 'svm':
224-
self.model = SVC(C=150, kernel='rbf')
225-
elif self.name == 'hsn':
251+
if self.name == 'hsn':
226252
self.input_shape, self.n_classes = args
227253
self.model = create_hsn_model(self.input_shape, self.n_classes) # Hybrid Spectral Net
254+
else:
255+
raise ValueError(f"Model {name} not supported")
228256

229257
def train(self, X, y, train_ratio=0.7, epochs=50):
230-
if self.name == 'svm':
231-
X_train, X_test, y_train, y_test = train_test_split(X.reshape(-1, X.shape[-1]), y, train_size=train_ratio, stratify=y)
232-
self.model.fit(X_train, y_train)
233-
return y_test, self.model.predict(X_test)
234-
elif self.name == 'hsn':
258+
if self.name == 'hsn':
235259
X = principal_components(X, n_components=self.input_shape[2])
236260
X_train, X_test, y_train, y_test = generate_training_data(X, y, self.input_shape[0], train_ratio)
237261
self.history = self.model.fit(x=X_train, y=np_utils.to_categorical(y_train), batch_size=256, epochs=epochs)
238262
return y_test, np.argmax(self.model.predict(X_test), axis=1)
239263

240264
def predict(self, X):
241-
if self.name == 'svm':
242-
return self.model.predict(X.reshape(-1, X.shape[2])).reshape(X.shape[0], X.shape[1])
243-
elif self.name == 'hsn':
265+
if self.name == 'hsn':
244266
X = principal_components(X, n_components=self.input_shape[2])
245267
return predict_hsn_model(self.model, X, self.input_shape[0])
246268

247-
def plot_history():
269+
def plot_history(self):
248270
if self.history:
249271
plot_train_history(self.history)
250272

@@ -256,5 +278,5 @@ def load(self, filename='model.h5'):
256278

257279

258280
def create_model(name, *args):
259-
"""Create a new model: svm or hsn"""
281+
"""Create a new model: hsn"""
260282
return HyperspectralModel(name, *args)

abraia/training/dataset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from ..client import Abraia
1313
from ..utils import HEADERS, load_image, load_url, list_dir, url_path
14+
from .ops import train_test_split
1415
from ..inference.detect import segment_objects
1516

1617

@@ -240,7 +241,6 @@ def save(self, annotations=None):
240241
save_annotations(self.project, self.annotations)
241242

242243
def split(self):
243-
from sklearn.model_selection import train_test_split
244244
# TODO: Split dataset by classes to avoid class imbalance
245245
backgrounds = [annotation for annotation in self.annotations if not annotation.get('objects')]
246246
annotations = [annotation for annotation in self.annotations if annotation.get('objects')]

images/screenshot.jpg

-1.6 KB
Loading

0 commit comments

Comments
 (0)