Kaynağa Gözat

Results + ROC Curves

Felix Kleinsteuber 3 yıl önce
ebeveyn
işleme
eaf6f49114
53 değiştirilmiş dosya ile 184 ekleme ve 207 silme
  1. 15 22
      approach1a_basic_frame_differencing.ipynb
  2. 24 23
      approach2_background_estimation.ipynb
  3. BIN
      approach2_results.npy
  4. 5 6
      approach3_local_features.ipynb
  5. 36 138
      approach4_autoencoder.ipynb
  6. 5 4
      eval_bow.py
  7. BIN
      plots/approach1a/roc_curves/Beaver_01.pdf
  8. BIN
      plots/approach1a/roc_curves/Beaver_01.png
  9. BIN
      plots/approach1a/roc_curves/Beaver_01_sigma2.pdf
  10. BIN
      plots/approach1a/roc_curves/Beaver_01_sigma2.png
  11. BIN
      plots/approach1a/roc_curves/Beaver_01_sigma4.pdf
  12. BIN
      plots/approach1a/roc_curves/Beaver_01_sigma4.png
  13. BIN
      plots/approach2/roc_curves/Beaver_01.pdf
  14. BIN
      plots/approach2/roc_curves/Beaver_01.png
  15. BIN
      plots/approach2/roc_curves/Marten_01.pdf
  16. BIN
      plots/approach2/roc_curves/Marten_01.png
  17. 0 0
      plots/approach3/beaver_01_bow_1024_30_tar_vs_tnr.png
  18. 0 0
      plots/approach3/beaver_01_bow_2048_30_tar_vs_tnr.png
  19. 0 0
      plots/approach3/beaver_01_bow_512_30_tar_vs_tnr.png
  20. 0 0
      plots/approach3/marten_01_bow_1024_30_tar_vs_tnr.png
  21. 0 0
      plots/approach3/marten_01_bow_2048_30_tar_vs_tnr.png
  22. 0 0
      plots/approach3/marten_01_bow_512_30_tar_vs_tnr.png
  23. BIN
      plots/approach3/roc_curves/Beaver_01_20_1024.pdf
  24. BIN
      plots/approach3/roc_curves/Beaver_01_20_1024.png
  25. BIN
      plots/approach3/roc_curves/Beaver_01_30_1024.pdf
  26. BIN
      plots/approach3/roc_curves/Beaver_01_30_1024.png
  27. BIN
      plots/approach3/roc_curves/Beaver_01_30_2048.pdf
  28. BIN
      plots/approach3/roc_curves/Beaver_01_30_2048.png
  29. BIN
      plots/approach3/roc_curves/Beaver_01_30_512.pdf
  30. BIN
      plots/approach3/roc_curves/Beaver_01_30_512.png
  31. BIN
      plots/approach3/roc_curves/Marten_01_30_1024.pdf
  32. BIN
      plots/approach3/roc_curves/Marten_01_30_1024.png
  33. BIN
      plots/approach3/roc_curves/Marten_01_30_2048.pdf
  34. BIN
      plots/approach3/roc_curves/Marten_01_30_2048.png
  35. BIN
      plots/approach3/roc_curves/Marten_01_30_512.pdf
  36. BIN
      plots/approach3/roc_curves/Marten_01_30_512.png
  37. BIN
      plots/approach4/roc_curves/Beaver_01_kde,loss.pdf
  38. BIN
      plots/approach4/roc_curves/Beaver_01_kde,loss.png
  39. BIN
      plots/approach4/roc_curves/Beaver_01_kde.pdf
  40. BIN
      plots/approach4/roc_curves/Beaver_01_kde.png
  41. BIN
      plots/approach4/roc_curves/Beaver_01_loss.pdf
  42. BIN
      plots/approach4/roc_curves/Beaver_01_loss.png
  43. BIN
      plots/approach4/roc_curves/Marten_01_kde,loss.pdf
  44. BIN
      plots/approach4/roc_curves/Marten_01_kde,loss.png
  45. BIN
      plots/approach4/roc_curves/Marten_01_kde.pdf
  46. BIN
      plots/approach4/roc_curves/Marten_01_kde.png
  47. BIN
      plots/approach4/roc_curves/Marten_01_loss.pdf
  48. BIN
      plots/approach4/roc_curves/Marten_01_loss.png
  49. 16 7
      py/LocalFeatures.py
  50. 21 0
      py/PlotUtils.py
  51. 2 2
      py/Session.py
  52. 54 0
      results.ipynb
  53. 6 5
      train_bow.py

Dosya farkı çok büyük olduğundan ihmal edildi
+ 15 - 22
approach1a_basic_frame_differencing.ipynb


Dosya farkı çok büyük olduğundan ihmal edildi
+ 24 - 23
approach2_background_estimation.ipynb


BIN
approach2_results.npy


Dosya farkı çok büyük olduğundan ihmal edildi
+ 5 - 6
approach3_local_features.ipynb


Dosya farkı çok büyük olduğundan ihmal edildi
+ 36 - 138
approach4_autoencoder.ipynb


+ 5 - 4
eval_bow.py

@@ -11,6 +11,7 @@ def main():
     parser.add_argument("dataset_dir", type=str, help="Directory of the dataset containing all session folders")
     parser.add_argument("session_name", type=str, help="Name of the session to use for Lapse images (e.g. marten_01)")
     parser.add_argument("--clusters", type=int, help="Number of clusters / BOW vocabulary size", default=1024)
+    parser.add_argument("--step_size", type=int, help="DSIFT keypoint step size. Smaller step size = more keypoints.", default=30)
 
     args = parser.parse_args()
 
@@ -20,9 +21,9 @@ def main():
 
     # Lapse DSIFT descriptors
 
-    dictionary_file = os.path.join(save_dir, f"bow_dict_{args.clusters}.npy")
-    train_feat_file = os.path.join(save_dir, f"bow_train_{args.clusters}.npy")
-    eval_file = os.path.join(save_dir, f"bow_eval_{args.clusters}.csv")
+    dictionary_file = os.path.join(save_dir, f"bow_dict_{args.step_size}_{args.clusters}.npy")
+    train_feat_file = os.path.join(save_dir, f"bow_train_{args.step_size}_{args.clusters}.npy")
+    eval_file = os.path.join(save_dir, f"bow_eval_{args.step_size}_{args.clusters}.csv")
 
     if not os.path.isfile(dictionary_file):
         print(f"ERROR: BOW dictionary missing! ({dictionary_file})")
@@ -41,7 +42,7 @@ def main():
 
         print("Evaluating...")
         with open(eval_file, "a+") as f:
-            for filename, feat in generate_bow_features(list(session.generate_motion_images()), dictionary):
+            for filename, feat in generate_bow_features(list(session.generate_motion_images()), dictionary, kp_step=args.step_size):
                 y = clf.decision_function(feat)[0]
                 f.write(f"{filename},{y}\n")
                 f.flush()

BIN
plots/approach1a/roc_curves/Beaver_01.pdf


BIN
plots/approach1a/roc_curves/Beaver_01.png


BIN
plots/approach1a/roc_curves/Beaver_01_sigma2.pdf


BIN
plots/approach1a/roc_curves/Beaver_01_sigma2.png


BIN
plots/approach1a/roc_curves/Beaver_01_sigma4.pdf


BIN
plots/approach1a/roc_curves/Beaver_01_sigma4.png


BIN
plots/approach2/roc_curves/Beaver_01.pdf


BIN
plots/approach2/roc_curves/Beaver_01.png


BIN
plots/approach2/roc_curves/Marten_01.pdf


BIN
plots/approach2/roc_curves/Marten_01.png


+ 0 - 0
plots/approach3/beaver_01_bow_1024_tar_vs_tnr.png → plots/approach3/beaver_01_bow_1024_30_tar_vs_tnr.png


+ 0 - 0
plots/approach3/beaver_01_bow_2048_tar_vs_tnr.png → plots/approach3/beaver_01_bow_2048_30_tar_vs_tnr.png


+ 0 - 0
plots/approach3/beaver_01_bow_512_tar_vs_tnr.png → plots/approach3/beaver_01_bow_512_30_tar_vs_tnr.png


+ 0 - 0
plots/approach3/marten_01_bow_1024_tar_vs_tnr.png → plots/approach3/marten_01_bow_1024_30_tar_vs_tnr.png


+ 0 - 0
plots/approach3/marten_01_bow_2048_tar_vs_tnr.png → plots/approach3/marten_01_bow_2048_30_tar_vs_tnr.png


+ 0 - 0
plots/approach3/marten_01_bow_512_tar_vs_tnr.png → plots/approach3/marten_01_bow_512_30_tar_vs_tnr.png


BIN
plots/approach3/roc_curves/Beaver_01_20_1024.pdf


BIN
plots/approach3/roc_curves/Beaver_01_20_1024.png


BIN
plots/approach3/roc_curves/Beaver_01_30_1024.pdf


BIN
plots/approach3/roc_curves/Beaver_01_30_1024.png


BIN
plots/approach3/roc_curves/Beaver_01_30_2048.pdf


BIN
plots/approach3/roc_curves/Beaver_01_30_2048.png


BIN
plots/approach3/roc_curves/Beaver_01_30_512.pdf


BIN
plots/approach3/roc_curves/Beaver_01_30_512.png


BIN
plots/approach3/roc_curves/Marten_01_30_1024.pdf


BIN
plots/approach3/roc_curves/Marten_01_30_1024.png


BIN
plots/approach3/roc_curves/Marten_01_30_2048.pdf


BIN
plots/approach3/roc_curves/Marten_01_30_2048.png


BIN
plots/approach3/roc_curves/Marten_01_30_512.pdf


BIN
plots/approach3/roc_curves/Marten_01_30_512.png


BIN
plots/approach4/roc_curves/Beaver_01_kde,loss.pdf


BIN
plots/approach4/roc_curves/Beaver_01_kde,loss.png


BIN
plots/approach4/roc_curves/Beaver_01_kde.pdf


BIN
plots/approach4/roc_curves/Beaver_01_kde.png


BIN
plots/approach4/roc_curves/Beaver_01_loss.pdf


BIN
plots/approach4/roc_curves/Beaver_01_loss.png


BIN
plots/approach4/roc_curves/Marten_01_kde,loss.pdf


BIN
plots/approach4/roc_curves/Marten_01_kde,loss.png


BIN
plots/approach4/roc_curves/Marten_01_kde.pdf


BIN
plots/approach4/roc_curves/Marten_01_kde.png


BIN
plots/approach4/roc_curves/Marten_01_loss.pdf


BIN
plots/approach4/roc_curves/Marten_01_loss.png


+ 16 - 7
py/LocalFeatures.py

@@ -7,36 +7,44 @@ from tqdm import tqdm
 
 from py.Session import SessionImage
 
-def dense_keypoints(img, step=30, off=(15, 12)):
-    """Generates a list of densely sampled keypoints on img.
+def dense_keypoints(img, step=30):
+    """Generates a list of densely sampled keypoints on img. The keypoints are arranged tightly
+    next to each other without spacing. The group of all keypoints is centered in the image.
 
     Args:
         img (_type_): Image to sample from. (only the shape is relevant)
         step (int, optional): Vertical and horizontal step size between and size of keypoints. Defaults to 30.
-        off (tuple, optional): y and x offset of the first keypoint in the grid. Defaults to (15, 12).
 
     Returns:
         list[cv.KeyPoint]: List of keypoints
     """
+    # calculate offset to center keypoints
+    off = ((img.shape[0] % step) // 2, (img.shape[1] % step) // 2)
     border_dist = (step + 1) // 2
     return [cv.KeyPoint(x, y, step) for y in range(border_dist + off[0], img.shape[0] - border_dist, step) 
                                     for x in range(border_dist + off[1], img.shape[1] - border_dist, step)]
 
 
-def extract_descriptors(images: list[SessionImage]):
+def extract_descriptors(images: list[SessionImage], kp_step: int = 30):
     """Extracts DSIFT descriptors from the provided images and returns them in a single array.
 
     Args:
         images (list[SessionImage]): List of images to read and compute descriptors from.
+        kp_step (int, optional): Keypoint step size, see dense_keypoints. Defaults to 30.
 
     Returns:
         np.array, shape=(len(images)*keypoints_per_image, 128): DSIFT descriptors.
     """
     sift = cv.SIFT_create()
     dscs = []
+    output_kp = False
     for image in tqdm(images):
         img = image.read_opencv(gray=True)
-        kp = dense_keypoints(img)
+        kp = dense_keypoints(img, kp_step)
+        # output number of keypoints once
+        if not output_kp:
+            print(f"{len(kp)} keypoints per image.")
+            output_kp = True
         kp, des = sift.compute(img, kp)
         dscs.append(des)
     return np.array(dscs)
@@ -58,13 +66,14 @@ def generate_dictionary_from_descriptors(dscs, dictionary_size: int):
     dictionary = BOW.cluster()
     return dictionary
 
-def generate_bow_features(images: list[SessionImage], dictionary):
+def generate_bow_features(images: list[SessionImage], dictionary, kp_step: int = 30):
     """Calculates the BOW features for the provided images using dictionary.
     Yields a feature vector for every image.
 
     Args:
         images (list[SessionImage]): List of images to read and compute feature vectors from.
         dictionary (np.array, shape=(-1, 128)): BOW dictionary.
+        kp_step (int, optional): Keypoint step size, see dense_keypoints. Must be identical to the step size used for vocabulary generation. Defaults to 30.
 
     Yields:
         (str, np.array of shape=(dictionary.shape[0])): (filename, feature vector)
@@ -76,6 +85,6 @@ def generate_bow_features(images: list[SessionImage], dictionary):
     
     for image in tqdm(images):
         img = image.read_opencv(gray=True)
-        kp = dense_keypoints(img)
+        kp = dense_keypoints(img, kp_step)
         feat = bow_extractor.compute(img, kp)
         yield image.filename, feat

+ 21 - 0
py/PlotUtils.py

@@ -0,0 +1,21 @@
+import matplotlib.pyplot as plt
+from sklearn.metrics import roc_curve, auc
+
+def plot_roc_curve(test_labels: list, test_df: list, title: str, figsize=(8, 8), savefile = None):
+    fpr, tpr, thresholds = roc_curve(test_labels, test_df)
+    auc_score = auc(fpr, tpr)
+
+    plt.figure(figsize=figsize)
+    plt.plot(fpr, tpr, lw=1, label="ROC Curve")
+    plt.plot([0, 1], [0, 1], color="lime", linestyle="--")
+    plt.xlim([0.0, 1.0])
+    plt.ylim([0.0, 1.05])
+    plt.xlabel("FPR")
+    plt.ylabel("TPR")
+    plt.title(f"{title} (AUC = {auc_score})")
+    plt.legend(loc="lower right")
+    if savefile is not None:
+        plt.savefig(f"{savefile}.png", bbox_inches="tight")
+        plt.savefig(f"{savefile}.pdf", bbox_inches="tight")
+    plt.show()
+    return fpr, tpr, thresholds, auc_score

+ 2 - 2
py/Session.py

@@ -197,9 +197,9 @@ class Session:
             date = random.choice(list(self.motion_map.keys()))
             filenames = self.motion_map.get(date, [])
             imgs = [MotionImage(self, filename, date) for filename in filenames]
-        # include all images within +- 10 min
+        # include all images within +- 5 min
         for other_date in self.motion_map.keys():
-            if date != other_date and abs((date - other_date).total_seconds()) <= 60 * 10:
+            if date != other_date and abs((date - other_date).total_seconds()) <= 60 * 5:
                 filenames = self.motion_map.get(other_date, [])
                 imgs += [MotionImage(self, filename, other_date) for filename in filenames]
         return imgs

+ 54 - 0
results.ipynb

@@ -0,0 +1,54 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Results"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Beaver_01\n",
+    "\n",
+    "| Approach | Configuration | Best AUC |\n",
+    "| --- | --- | ---: |\n",
+    "| 1a - Basic Frame Differencing | - | 0.7335 |\n",
+    "| | $\\sigma=2$ | 0.8658 |\n",
+    "| | $\\sigma=4$ | 0.8747 |\n",
+    "| 2 - Background Estimation | No Lapse | 0.7524 |\n",
+    "| 3 - BOW | $k=2048, kp=30$ | 0.7741 |\n",
+    "| 4 - Autoencoder | Deep +Noise +Sparse KDE | 0.9209 |"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "\n",
+    "## Marten_01\n",
+    "\n",
+    "| Approach | Configuration | Best AUC |\n",
+    "| --- | --- | ---: |\n",
+    "| 2 - Background Estimation | No Lapse | 0.5832 |\n",
+    "| 3 - BOW | $k=1024, kp=30$ | 0.7099 |\n",
+    "| 4 - Autoencoder | Deep +Noise +Sparse KDE | 1.0000 |"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": []
+  }
+ ],
+ "metadata": {
+  "language_info": {
+   "name": "python"
+  },
+  "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}

+ 6 - 5
train_bow.py

@@ -15,6 +15,7 @@ def main():
     parser.add_argument("dataset_dir", type=str, help="Directory of the dataset containing all session folders")
     parser.add_argument("session_name", type=str, help="Name of the session to use for Lapse images (e.g. marten_01)")
     parser.add_argument("--clusters", type=int, help="Number of clusters / BOW vocabulary size", default=1024)
+    parser.add_argument("--step_size", type=int, help="DSIFT keypoint step size. Smaller step size = more keypoints.", default=30)
 
     args = parser.parse_args()
 
@@ -24,9 +25,9 @@ def main():
 
     # Lapse DSIFT descriptors
 
-    lapse_dscs_file = os.path.join(save_dir, "lapse_dscs.npy")
-    dictionary_file = os.path.join(save_dir, f"bow_dict_{args.clusters}.npy")
-    train_feat_file = os.path.join(save_dir, f"bow_train_{args.clusters}.npy")
+    lapse_dscs_file = os.path.join(save_dir, f"lapse_dscs_{args.step_size}.npy")
+    dictionary_file = os.path.join(save_dir, f"bow_dict_{args.step_size}_{args.clusters}.npy")
+    train_feat_file = os.path.join(save_dir, f"bow_train_{args.step_size}_{args.clusters}.npy")
 
     if os.path.isfile(lapse_dscs_file):
         if os.path.isfile(dictionary_file):
@@ -38,7 +39,7 @@ def main():
     else:
         # Step 1 - extract dense SIFT descriptors
         print("Extracting lapse descriptors...")
-        lapse_dscs = extract_descriptors(list(session.generate_lapse_images()))
+        lapse_dscs = extract_descriptors(list(session.generate_lapse_images()), kp_step=args.step_size)
         os.makedirs(save_dir, exist_ok=True)
         np.save(lapse_dscs_file, lapse_dscs)
 
@@ -60,7 +61,7 @@ def main():
     else:
         # Step 3 - calculate training data (BOW features of Lapse images)
         print(f"Extracting BOW features from Lapse images...")
-        features = list(generate_bow_features(list(session.generate_lapse_images()), dictionary))
+        features = [feat for _, feat in generate_bow_features(list(session.generate_lapse_images()), dictionary, kp_step=args.step_size)]
         np.save(train_feat_file, features)
     
     print("Complete!")

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor