Commit fb7f6c7e authored by Gaetano Raffaele's avatar Gaetano Raffaele
Browse files

ENH: object based training pipeline complete.

No related merge requests found
Showing with 54 additions and 3 deletions
+54 -3
import glob
from OBIA.OBIABase import *
from sklearn.model_selection import StratifiedGroupKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix, accuracy_score, cohen_kappa_score, precision_recall_fscore_support
class ObjectBasedClassifier:
def __init__(self, object_layer, reference_data, time_series_patterns, user_feature_list):
self.obia_base = OBIABase(object_layer, ref_data = reference_data)
for ptrn in time_series_patterns:
lst = sorted(glob.glob(ptrn))
self.obia_base.add_raster_time_series_for_stats(lst)
for ras in user_feature_list:
self.obia_base.add_raster_for_stats(ras)
self.obia_base.populate_ref_db()
def train_RF(self, n_estimators, n_folds):
L, X, Y, G, p2, p98 = self.obia_base.get_reference_db_as_training_base()
sgk = StratifiedGroupKFold(n_splits=n_folds, shuffle=True)
folds_indices = []
models = []
results = []
for tr_i, ts_i in sgk.split(X, Y, G):
folds_indices.append((tr_i, ts_i))
models.append(RandomForestClassifier(n_estimators=n_estimators))
models[-1].fit(X[tr_i], Y[tr_i])
l, c = L[ts_i], models[-1].predict(X[ts_i])
y_true, y_pred = self.obia_base.true_pred_bypixel(l, c)
results.append(
{
'conf_matrix': confusion_matrix(y_true, y_pred),
'accuracy': accuracy_score(y_true, y_pred),
'kappa' : cohen_kappa_score(y_true, y_pred),
'p_r_f1': precision_recall_fscore_support(y_true, y_pred)
}
)
return folds_indices, models, results
......@@ -69,7 +69,10 @@ class OBIABase:
obj = in_seg.GetImageAsNumpyArray('out')
mask = ids>0
self.ref_obj_layer = label(obj * mask, connectivity=1).astype(np.uint32)
# This was to relabel object being disconnected by intersecting the GT
# Re-enable if needed...
# self.ref_obj_layer = label(obj * mask, connectivity=1).astype(np.uint32)
self.ref_obj_layer = (obj * mask).astype(np.uint32)
rp = regionprops(self.ref_obj_layer, intensity_image=np.dstack((obj,ids,cls)).astype(np.int))
self.ref_db = pd.DataFrame(data=[np.insert(o.intensity_min,0,o.area) for o in rp],
columns=['area','orig_label','polygon_id','class'],
......@@ -219,6 +222,7 @@ class OBIABase:
def get_reference_db_as_training_base(self):
assert(self.ref_db is not None and len(self.raster_var_names)>0)
vars = [item for sublist in self.raster_var_names for item in sublist]
L = self.ref_db['orig_label'].to_numpy(dtype=int)
X = self.ref_db[vars].to_numpy()
# compute percentiles and normalize
p2 = np.zeros(X.shape[1])
......@@ -236,7 +240,7 @@ class OBIABase:
X[:,g] = (tmp - m)/(M - m)
Y = self.ref_db['class'].to_numpy(dtype=int)
G = self.ref_db['polygon_id'].to_numpy(dtype=int)
return X,Y,G,p2,p98
return L,X,Y,G,p2,p98
def tiled_data(self, normalize=None):
vars = [item for sublist in self.raster_var_names for item in sublist]
......@@ -249,4 +253,14 @@ class OBIABase:
yield L,X
def populate_map(self, tilenum, labels):
return
\ No newline at end of file
return
def true_pred_bypixel(self, labels, predicted_classes):
pred_c = np.zeros(np.max(self.ref_obj_layer)+1)
pred_c[labels] = predicted_classes
pred = pred_c[self.ref_obj_layer]
true_c = np.zeros(np.max(self.ref_db['orig_label']).astype(int)+1)
# ATTENTION: works if "labels" is sorted (as provided by get_reference_...)
true_c[labels] = self.ref_db.loc[self.ref_db['orig_label'].isin(labels),'class'].to_numpy(dtype=int)
true = true_c[self.ref_obj_layer]
return pred[pred>0], true[pred>0]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment