浏览代码

updated READMEs and added part __repr__ function

Dimitri Korsch 6 年之前
父节点
当前提交
1b50fcfadb
共有 4 个文件被更改,包括 100 次插入22 次删除
  1. 87 15
      README.md
  2. 0 6
      nabirds/dataset/README.md
  3. 13 0
      nabirds/dataset/part.py
  4. 0 1
      scripts/display_from_info.py

+ 87 - 15
README.md

@@ -18,6 +18,62 @@ test_data = Dataset(uuids=annot.test_uuids, annotations=annot)
 print("Loaded {} training and {} test images".format(len(train_data), len(test_data)))
 ```
 
+Alternatively, you can create an annotation and a dataset instance from a YAML dataset file:
+
+```python
+annot = NAB_Annotations("path/to/yaml/config_file.yml")
+
+train_data = annot.new_dataset("train")
+test_data = annot.new_dataset("test")
+```
+
+An example YAML dataset file could be the following:
+
+```yaml
+BASE_DIR: /data/your_data_folder/
+
+# in BASE_DIR should be "datasets" and "models" folder
+DATA_DIR: datasets
+MODEL_DIR: models
+
+
+# in /data/your_data_folder/datasets should be "birds" and  there should be a "cub200_11" folder with the CUB200 dataset. this represents default annotation folder.
+DATASETS:
+  CUB200:         &cub200
+    folder: birds
+    annotations: cub200_11
+
+# Here we define different types of part annotations
+PARTS:
+  # uniform 5x5 parts
+  UNI:            &parts_uni
+    <<: *cub200
+    is_uniform: true
+    annotations: cub200_11
+    rescale_size: !!int -1
+    scales:
+     - 0.2
+
+  # ground truth parts
+  GT:             &parts_gt
+    <<: *cub200
+    annotations: cub200_11
+    rescale_size: !!int -1
+    scales:
+     - 0.31
+
+  # NAC parts with 2 scales
+  NAC:            &parts_nac
+    <<: *cub200
+    annotations: NAC/2017-bilinear
+    feature_suffix: 20parts_gt
+    rescale_size: !!int 224
+    scales:
+      - 0.31
+      - 0.45
+```
+
+
 ## Dataset Iteration
 ```python
 import matplotlib.pyplot as plt
@@ -53,16 +109,19 @@ print(parts)
 #        [  8, 365, 751,   1],
 #        [  9,   0,   0,   0],
 #        [ 10,   0,   0,   0]])
-
+...
 ```
+
+
+
 ### Visible Parts
 
-In order to filter by only visible parts use the [`utils.visible_part_locs`](nabirds/dataset/utils.py#L28) function. It returns the indices and the x-y positions of the visible parts:
+In order to filter by only visible parts use the [`visible_locs`](nabirds/dataset/part.py#L46) method. It returns the indices and the x-y positions of the visible parts:
 
 ```python
-from nabirds import utils
+...
 
-idxs, xy = utils.visible_part_locs(parts)
+idxs, xy = parts.visible_locs()
 
 print(idxs)
 # array([0, 1, 2, 4, 5, 6, 8])
@@ -81,10 +140,11 @@ In case you don't want to use the ground truth parts, you can generate parts uni
 
 
 ```python
-from nabirds import utils
+...
+from nabirds.dataset.part import UniformParts
 
-parts = utils.uniform_parts(im, ratio=1/3)
-idxs, xy = utils.visible_part_locs(parts)
+parts = UniformParts(im, ratio=1/3)
+idxs, xy = parts.visible_locs()
 
 print(idxs)
 # array([0, 1, 2, 3, 4, 5, 6, 7, 8])
@@ -96,15 +156,16 @@ x, y = xy
 plt.imshow(im)
 plt.scatter(x,y, marker="x", c=idxs)
 plt.show()
+...
 ```
 
 ### Crop Extraction
-From the locations we can also extract some crops. Same as in [`utils.uniform_parts`](nabirds/dataset/utils.py#L9) you have to give a ratio with which the crops around the locations are created:
+From the locations we can also extract some crops. Same as in [`UniformParts`](nabirds/dataset/part.py#L76) you have to give a ratio with which the crops around the locations are created:
 
 ```python
-from nabirds import utils
+...
 
-part_crops = utils.visible_crops(im, parts, ratio=0.2)
+part_crops = parts.visible_crops(im, ratio=0.2)
 
 fig = plt.figure(figsize=(16,9))
 n_crops = part_crops.shape[0]
@@ -117,16 +178,26 @@ for j, crop in enumerate(part_crops, 1):
     ax.axis("off")
 
 plt.show()
+...
 ```
 
 
 ### Random Crops
-In some cases randomly selected crops are desired. Here you can use the [`utils.random_select`](nabirds/dataset/utils.py#L76) function. As optional argument you can also pass a `rnd` argument, that can be an integer (indicating a random seed) or a `numpy.random.RandomState` instance. Additionally, you can also determine the number of crops that will be selected (default is to select random number of crops).
+In some cases randomly selected crops are desired. Here you can use the [`utils.random_index`](nabirds/utils/__init__.py#L3) function. As optional argument you can also pass a `rnd` argument, that can be an integer (indicating a random seed) or a `numpy.random.RandomState` instance. Additionally, you can also determine the number of crops that will be selected (default is to select random number of crops).
 
 ```python
+...
 from nabirds import utils
+import copy
+
+part_crops = parts.visible_crops(im, ratio=0.2)
+idxs, xy = parts.visible_locs()
 
-rnd_idxs, rnd_xy, rnd_part_crops = utils.random_select(idxs, xy, part_crops)
+rnd_parts = copy.deepcopy(parts)
+rnd_idxs = utils.random_idxs(idxs, rnd=rnd, n_parts=n_parts)
+rnd_parts.select(rnd_idxs)
+# now only selected parts are visible
+rnd_part_crops = rnd_parts.visible_crops(im, ratio=0.2)
 
 fig = plt.figure(figsize=(16,9))
 
@@ -140,18 +211,19 @@ for j, crop in zip(rnd_idxs, rnd_part_crops):
     ax.axis("off")
 
 plt.show()
+...
 ```
 
 
 ### Revealing of the Parts
-In order to create a single image, that consist of the given parts on their correct location use [`utils.reveal_parts`](nabirds/dataset/utils.py#L57) function. It requires again besides the original image and the locations the ratio with which the parts around the locations should be revealed:
+In order to create a single image, that consist of the given parts on their correct location use [`reveal`](nabirds/dataset/part.py#L58) function. It requires again besides the original image and the locations the ratio with which the parts around the locations should be revealed:
 
 ```python
 
-plt.imshow(reveal_parts(im, xy, ratio=0.2))
+plt.imshow(parts.reveal(im, ratio=0.2))
 plt.show()
 
-plt.imshow(reveal_parts(im, rnd_xy, ratio=0.2))
+plt.imshow(rnd_parts.reveal(im, ratio=0.2))
 plt.show()
 ```
 

+ 0 - 6
nabirds/dataset/README.md

@@ -36,9 +36,3 @@ data = Dataset(
 ```
 
 Information about all possible [`PartMixing`](mixins/parts.py) functionalities can be found [here](mixins).
-
-All of the used part and bounding box functionalities can be manually used with the help of the [`utils`](utils.py) module.
-
-## `utils` module
-
-TBD (see [main page](../../#working-with-part-annotations) for more information for now)

+ 13 - 0
nabirds/dataset/part.py

@@ -12,6 +12,9 @@ class BaseParts(ABC):
 	def __getitem__(self, i):
 		return self._parts[i]
 
+	def __repr__(self):
+		return repr(np.stack([p.as_annotation for p in self._parts]))
+
 	@property
 	def selected(self):
 		return np.array([p.is_visible for p in self._parts], dtype=bool)
@@ -96,6 +99,9 @@ class UniformParts(BaseParts):
 
 class BasePart(ABC):
 
+	def __repr__(self):
+		return repr(self.as_annotation)
+
 	@staticmethod
 	def new(image, annotation, rescale_size=-1):
 		if len(annotation) == 4:
@@ -165,6 +171,9 @@ class LocationPart(BasePart):
 		self._id, self.x, self.y, self.is_visible = annotation
 		self._ratio = LocationPart.DEFAULT_RATIO
 
+	def as_annotation(self):
+		return np.array([self._id, self.x, self.y, self.is_visible])
+
 	def crop(self, image, ratio=None, padding_mode="edge", *args, **kwargs):
 		ratio = ratio or self._ratio
 		_h, _w, c = utils.dimensions(image)
@@ -208,6 +217,10 @@ class BBoxPart(BasePart):
 		self._id, self.x, self.y, self.w, self.h = annotation
 		self.is_visible = True
 
+	@property
+	def as_annotation(self):
+		return np.array([self._id, self.x, self.y, self.w, self.h])
+
 	def rescale(self, image, annotation, rescale_size):
 		if rescale_size is not None and rescale_size > 0:
 			annotation = super(BBoxPart, self).rescale(image, annotation, rescale_size)

+ 0 - 1
scripts/display_from_info.py

@@ -76,7 +76,6 @@ def main(args):
 	for i in range(start, max(start, start + n_images)):
 		im, parts, label = data[i]
 
-
 		fig1, axs = plt.subplots(2, 1, figsize=(16,9))
 		axs[0].axis("off")
 		axs[0].set_title("Visible Parts")