Browse Source

added Stanford Cars annotation implementation

Dimitri Korsch 6 năm trước cách đây
mục cha
commit
8ea16b5474

+ 3 - 1
nabirds/annotations/__init__.py

@@ -1,10 +1,12 @@
 from .cub import CUB_Annotations
 from .nab import NAB_Annotations
+from .cars import CARS_Annotations
 
 from cvargparse.utils import BaseChoiceType
 
 class AnnotationType(BaseChoiceType):
-	NAB = NAB_Annotations
 	CUB = CUB_Annotations
+	NAB = NAB_Annotations
+	CARS = CARS_Annotations
 
 	Default = CUB

+ 9 - 5
nabirds/annotations/base.py

@@ -79,12 +79,16 @@ class BaseAnnotations(abc.ABC):
 		dataset_info = self.dataset_info
 		if dataset_info is None:
 			return kwargs
+		logging.debug("Dataset info: {}".format(dataset_info))
 
 		# TODO: pass all scales
-		new_opts = {
-			"ratio": dataset_info.scales[0],
-			"uniform_parts": dataset_info.is_uniform
-		}
+		new_opts = {}
+
+		if "scales" in dataset_info:
+			new_opts["ratio"] = dataset_info.scales[0]
+
+		if "is_uniform" in dataset_info:
+			new_opts["uniform_parts"] = dataset_info.is_uniform
 
 		if self.part_type is not None:
 			new_opts["part_rescale_size"] = dataset_info.rescale_size
@@ -106,7 +110,7 @@ class BaseAnnotations(abc.ABC):
 			new_opts["features"] = feature_path
 		new_opts.update(kwargs)
 
-		logging.debug(new_opts)
+		logging.debug("Final kwargs: {}".format(new_opts))
 		return new_opts
 
 	@property

+ 62 - 0
nabirds/annotations/cars.py

@@ -0,0 +1,62 @@
+import numpy as np
+
+from os.path import join
+
+from nabirds.utils import _MetaInfo
+from .base import BaseAnnotations
+
+
+class CARS_Annotations(BaseAnnotations):
+	name="CARS"
+
+	@property
+	def meta(self):
+		info = _MetaInfo(
+			images_folder="images",
+			images_file="images.txt",
+			labels_file="labels.txt",
+			split_file="tr_ID.txt",
+			bounding_boxes="bounding_boxes.txt",
+			bounding_box_dtype=np.dtype([(v, np.int32) for v in "xywh"]),
+		)
+
+		info.structure = [
+			[info.images_file, "_images"],
+			[info.labels_file, "labels"],
+			[info.split_file, "_split"],
+			[info.bounding_boxes, "_bounding_boxes"],
+		]
+		return info
+
+	def __init__(self, *args, **kwargs):
+		super(CARS_Annotations, self).__init__(*args, **kwargs)
+		# set labels from [1..N] to [0..N-1]
+		self.labels -= 1
+
+	def _load_split(self):
+		assert self._split is not None, "Train-test split was not loaded!"
+		uuid_to_split = {uuid: int(split) for uuid, split in zip(self.uuids, self._split)}
+		self.train_split = np.array([uuid_to_split[uuid] for uuid in self.uuids], dtype=bool)
+		self.test_split = np.logical_not(self.train_split)
+
+	def _load_parts(self):
+		self.part_names = {}
+		self._load_bounding_boxes()
+
+	def _load_bounding_boxes(self):
+		assert self._bounding_boxes is not None, "Bouding boxes were not loaded!"
+
+		uuid_to_bbox = {}
+		for content in [i.split() for i in self._bounding_boxes]:
+			uuid, bbox = content[0], content[1:]
+			uuid_to_bbox[uuid] = [float(i) for i in bbox]
+
+		self.bounding_boxes = np.array(
+			[tuple(uuid_to_bbox[uuid]) for uuid in self.uuids],
+			dtype=self.meta.bounding_box_dtype)
+
+	def parts(self, *args, **kwargs):
+		return None
+
+	def bounding_box(self, uuid):
+		return self.bounding_boxes[self.uuid_to_idx[uuid]].copy()

+ 4 - 1
nabirds/dataset/part/collection.py

@@ -9,7 +9,10 @@ class Parts(BasePartCollection):
 
 	def __init__(self, image, part_annotations, rescale_size):
 		super(Parts, self).__init__()
-		self._parts = [BasePart.new(image, a, rescale_size) for a in part_annotations]
+		if part_annotations is None:
+			self._parts = []
+		else:
+			self._parts = [BasePart.new(image, a, rescale_size) for a in part_annotations]
 
 
 class UniformParts(BasePartCollection):

+ 16 - 1
scripts/info_files/info.yml

@@ -8,14 +8,17 @@ MODELS:
   InceptionV3:    &inception
     folder: inception
     weights: ft_inat/model.ckpt.npz
+    ft_weights: ft_inat/model.ckpt.npz
 
   TFInceptionV3:  &inception_tf
     folder: inception_tf
     weights: ft_inat/inception_v3_iNat_299.ckpt
+    ft_weights: ft_inat/inception_v3_iNat_299.ckpt
 
   ResNet50:       &resnet50
     folder: resnet
-    weights: ft_cub200/model.npz
+    weights: model.npz
+    ft_weights: ft_cub200/model.npz
 
 ############ Existing Datasets
 DATASETS:
@@ -23,8 +26,20 @@ DATASETS:
     folder: birds
     annotations: cub200_11_ORIGINAL
 
+  CARS:         &cars
+    folder: cars
+    annotations: ORIGINAL
+
 ############ Existing Part Annotations and Part Features
 PARTS:
+  CARS_UNI:         &cars_uni
+    <<: *cars
+    is_uniform: true
+    feature_suffix: 26parts_uniform
+    rescale_size: !!int -1
+    scales:
+     - 0.2
+
   UNI:            &parts_uni
     <<: *cub200
     is_uniform: true

+ 1 - 0
scripts/utils/__init__.py

@@ -5,6 +5,7 @@ import matplotlib.pyplot as plt
 def plot_crops(crops, title, scatter_mid=False, names=None):
 
 	n_crops = crops.shape[0]
+	if n_crops == 0: return
 	rows = int(np.ceil(np.sqrt(n_crops)))
 	cols = int(np.ceil(n_crops / rows))
 

+ 4 - 1
scripts/utils/parser.py

@@ -14,7 +14,10 @@ def parse_args():
 			help_text="Type of the annotation"),
 
 		Arg("--parts", "-p",
-			choices=["GT", "GT2", "NAC", "UNI", "L1_pred", "L1_full"]),
+			choices=[
+				"GT", "GT2", "NAC", "UNI", "L1_pred", "L1_full",
+				"CARS_UNI"
+			]),
 
 
 		Arg("--feature_model", "-fm",