Browse Source

merged display scripts to one script; added new dependency: cvargparse; added annotation type class

Dimitri Korsch 6 years ago
parent
commit
2678ac17ce

+ 8 - 0
nabirds/annotations/__init__.py

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

+ 1 - 1
nabirds/dataset/part.py

@@ -1,7 +1,7 @@
 import numpy as np
-from matplotlib import pyplot as plt
 
 from contextlib import contextmanager
+from matplotlib import pyplot as plt
 from matplotlib.patches import Rectangle
 from abc import ABC, abstractproperty
 

+ 1 - 1
nabirds/utils/__init__.py

@@ -18,7 +18,7 @@ class attr_dict(dict):
 		if name in self:
 			return self[name]
 		else:
-			return super(attr_dict, self).__getattr__(name)
+			return super(attr_dict, self).get(name)
 
 	def __getitem__(self, key):
 		res = super(attr_dict, self).__getitem__(key)

+ 3 - 0
requirements.txt

@@ -2,3 +2,6 @@
 numpy
 pillow
 matplotlib
+pyyaml
+
+cvargparse~=0.5

+ 18 - 122
scripts/display.py

@@ -9,56 +9,28 @@ import matplotlib.pyplot as plt
 
 from argparse import ArgumentParser
 
-from nabirds import NAB_Annotations, CUB_Annotations
-
-
-def init_logger(args):
-	fmt = "%(levelname)s - [%(asctime)s] %(filename)s:%(lineno)d [%(funcName)s]: %(message)s"
-	logging.basicConfig(
-		format=fmt,
-		level=getattr(logging, args.loglevel.upper(), logging.DEBUG),
-		filename=args.logfile or None,
-		filemode="w")
-
-def plot_crops(crops, title, scatter_mid=False, names=None):
-
-	n_crops = crops.shape[0]
-	rows = int(np.ceil(np.sqrt(n_crops)))
-	cols = int(np.ceil(n_crops / rows))
-
-	fig, axs = plt.subplots(rows, cols, figsize=(16,9))
-	fig.suptitle(title, fontsize=16)
-	for i, crop in enumerate(crops):
-		ax = axs[np.unravel_index(i, axs.shape)]
-		if names is not None:
-			ax.set_title(names[i])
-		ax.imshow(crop)
-		ax.axis("off")
-		if scatter_mid:
-			middle_h, middle_w = crop.shape[0] / 2, crop.shape[1] / 2
-			ax.scatter(middle_w, middle_h, marker="x")
+from nabirds.annotations import AnnotationType
+from utils import parser, plot_crops
 
 def main(args):
-	init_logger(args)
 
-	annotation_cls = dict(
-		nab=NAB_Annotations,
-		cub=CUB_Annotations)
+	annotation_cls = AnnotationType.get(args.dataset).value
 
 	logging.info("Loading \"{}\" annnotations from \"{}\"".format(args.dataset, args.data))
-	annot = annotation_cls.get(args.dataset.lower())(args.data)
-
-	subset = args.subset
-
-	uuids = getattr(annot, "{}_uuids".format(subset))
-	features = args.features[0 if subset == "train" else 1]
+	annot = annotation_cls(args.data, args.parts, args.feature_model)
+
+	kwargs = {}
+	if annot.info is None:
+		# features = args.features[0 if args.subset == "train" else 1]
+		kwargs = dict(
+			part_rescale_size=args.rescale_size,
+			# features=features,
+			uniform_parts=args.uniform_parts,
+			ratio=args.ratio,
+		)
 
 	data = annot.new_dataset(
-		subset,
-		part_rescale_size=args.rescale_size,
-		# features=features,
-
-		uniform_parts=args.uniform_parts,
+		args.subset,
 
 		crop_to_bb=args.crop_to_bb,
 		crop_uniform=args.crop_uniform,
@@ -66,12 +38,12 @@ def main(args):
 		parts_in_bb=args.parts_in_bb,
 
 		rnd_select=args.rnd,
-		ratio=args.ratio,
-		seed=args.seed
+		seed=args.seed,
 
+		**kwargs
 	)
 
-	logging.info("Loaded {} {} images".format(len(data), subset))
+	logging.info("Loaded {} {} images".format(len(data), args.subset))
 
 	start = max(args.start, 0)
 	n_images = min(args.n_images, len(data) - start)
@@ -110,80 +82,4 @@ def main(args):
 		plt.show()
 		plt.close()
 
-parser = ArgumentParser()
-
-parser.add_argument("data",
-	help="Folder containing the dataset with images and annotation files",
-	type=str)
-
-parser.add_argument("--dataset",
-	help="Possible datasets: NAB, CUB",
-	choices=["cub", "nab"],
-	default="cub", type=str
-	)
-
-
-parser.add_argument("--subset", "-sub",
-	help="Possible subsets: train, test",
-	choices=["train", "test"],
-	default="train", type=str)
-
-
-parser.add_argument("--start", "-s",
-	help="Image id to start with",
-	type=int, default=0)
-
-parser.add_argument("--n_images", "-n",
-	help="Number of images to display",
-	type=int, default=10)
-
-
-parser.add_argument("--features",
-	help="pre-extracted train and test features",
-	default=[None, None],
-	nargs=2, type=str)
-
-parser.add_argument("--ratio",
-	help="Part extraction ratio",
-	type=float, default=.2)
-
-parser.add_argument("--rescale_size",
-	help="rescales the part positions from this size to original image size",
-	type=int, default=-1)
-
-parser.add_argument("--uniform_parts", "-u",
-	help="Do not use GT parts, but sample parts uniformly from the image",
-	action="store_true")
-
-
-parser.add_argument("--rnd",
-	help="select random subset of present parts",
-	action="store_true")
-
-parser.add_argument("--crop_to_bb",
-	help="Crop image to the bounding box",
-	action="store_true")
-
-parser.add_argument("--crop_uniform",
-	help="Try to extend the bounding box to same height and width",
-	action="store_true")
-
-parser.add_argument("--parts_in_bb",
-	help="Only display parts, that are inside the bounding box",
-	action="store_true")
-
-
-
-parser.add_argument(
-	'--logfile', type=str, default='',
-	help='File for logging output')
-
-parser.add_argument(
-	'--loglevel', type=str, default='INFO',
-	help='logging level. see logging module for more information')
-
-parser.add_argument(
-	'--seed', type=int, default=12311123,
-	help='random seed')
-
 main(parser.parse_args())

+ 24 - 5
scripts/display.sh

@@ -1,12 +1,31 @@
 #!/usr/bin/env bash
 PYTHON=python
-# Possible calls:
 
-# ./display.sh /home/korsch1/korsch/datasets/birds/cub200_11 --dataset cub -s600 -n5 --features /home/korsch1/korsch/datasets/birds/features/{train,val}_16parts_gt.npz --ratio 0.31
-# > displays GT parts of CUB200
+############## Possible calls ##############
 
-# ./display.sh /home/korsch1/korsch/datasets/birds/NAC/2017-bilinear/ --dataset cub -s600 -n5 --features /home/korsch1/korsch/datasets/birds/features/{train,val}_16parts_gt.npz --ratio 0.31 --rescale_size 227
-# > displays NAC parts of CUB200
+##### displays GT parts of CUB200
+# ./display.sh /home/korsch1/korsch/datasets/birds/cub200_11 \
+# 	--dataset cub \
+# 	-s600 -n5 \
+# 	--features /home/korsch1/korsch/datasets/birds/features/{train,val}_16parts_gt.npz \
+# 	--ratio 0.31
+
+
+##### displays NAC parts of CUB200
+# ./display.sh /home/korsch1/korsch/datasets/birds/NAC/2017-bilinear/ \
+# 	--dataset cub \
+# 	-s600 -n5 \
+# 	--features /home/korsch1/korsch/datasets/birds/features/{train,val}_20parts.npz \
+# 	--ratio 0.31 \
+# 	--rescale_size 227
+
+##### load from info file, displays Uniform parts of CUB200 that are in the GT bounding box
+# ./display.sh ~/DATA/info.yml \
+# 	-p UNI \
+# 	-s600 -n3 \
+# 	--parts_in_bb
+
+############################################
 
 $PYTHON display.py $@
 

+ 0 - 178
scripts/display_from_info.py

@@ -1,178 +0,0 @@
-#!/usr/bin/env python
-if __name__ != '__main__': raise Exception("Do not import me!")
-import sys
-sys.path.insert(0, "..")
-
-import logging
-import numpy as np
-import matplotlib.pyplot as plt
-
-from argparse import ArgumentParser
-
-from nabirds import NAB_Annotations, CUB_Annotations
-
-
-def init_logger(args):
-	fmt = "%(levelname)s - [%(asctime)s] %(filename)s:%(lineno)d [%(funcName)s]: %(message)s"
-	logging.basicConfig(
-		format=fmt,
-		level=getattr(logging, args.loglevel.upper(), logging.DEBUG),
-		filename=args.logfile or None,
-		filemode="w")
-
-
-def plot_crops(crops, title, scatter_mid=False, names=None):
-
-	n_crops = crops.shape[0]
-	rows = int(np.ceil(np.sqrt(n_crops)))
-	cols = int(np.ceil(n_crops / rows))
-
-	fig, axs = plt.subplots(rows, cols, figsize=(16,9))
-	fig.suptitle(title, fontsize=16)
-	for i, crop in enumerate(crops):
-		ax = axs[np.unravel_index(i, axs.shape)]
-		if names is not None:
-			ax.set_title(names[i])
-		ax.imshow(crop)
-		ax.axis("off")
-		if scatter_mid:
-			middle_h, middle_w = crop.shape[0] / 2, crop.shape[1] / 2
-			ax.scatter(middle_w, middle_h, marker="x")
-
-
-def main(args):
-	init_logger(args)
-
-	annotation_cls = dict(
-		nab=NAB_Annotations,
-		cub=CUB_Annotations)
-
-	logging.info("Loading \"{}\" annnotations from \"{}\"".format(args.dataset, args.data))
-	annot = annotation_cls.get(args.dataset.lower())(
-		args.data, args.parts, args.feature_model)
-
-	logging.info("Loaded data from \"{}\"".format(annot.root))
-
-	subset = args.subset
-
-	uuids = getattr(annot, "{}_uuids".format(subset))
-
-	data = annot.new_dataset(
-		subset,
-
-		crop_to_bb=args.crop_to_bb,
-		crop_uniform=args.crop_uniform,
-
-		parts_in_bb=args.parts_in_bb,
-
-		rnd_select=args.rnd,
-		seed=args.seed
-	)
-
-	logging.info("Loaded {} {} images".format(len(data), subset))
-
-	start = max(args.start, 0)
-	n_images = min(args.n_images, len(data) - start)
-
-	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")
-		axs[0].imshow(im)
-		if not args.crop_to_bb:
-			data.plot_bounding_box(i, axs[0])
-		parts.plot(im=im, ax=axs[0], ratio=data.ratio)
-
-		axs[1].axis("off")
-		axs[1].set_title("{}selected parts".format("randomly " if args.rnd else ""))
-		axs[1].imshow(parts.reveal(im, ratio=data.ratio))
-
-		if data.uniform_parts:
-			crop_names = None
-		else:
-			crop_names = list(data._annot.part_names.values())
-
-		part_crops = parts.visible_crops(im, ratio=data.ratio)
-		if args.rnd:
-			parts.invert_selection()
-			action_crops = parts.visible_crops(im, ratio=data.ratio)
-
-		plot_crops(part_crops, "Selected parts", names=crop_names)
-
-		if args.rnd:
-			plot_crops(action_crops, "Actions", names=crop_names)
-
-		plt.show()
-		plt.close()
-
-parser = ArgumentParser()
-
-parser.add_argument("data",
-	help="Folder containing the dataset with images and annotation files or dataset info file",
-	type=str)
-
-parser.add_argument("--dataset",
-	help="Possible datasets: NAB, CUB",
-	choices=["cub", "nab"],
-	default="cub", type=str
-)
-
-
-parser.add_argument("--parts", "-p",
-	choices=["GT", "GT2", "NAC", "UNI", "L1_pred", "L1_full"]
-)
-
-parser.add_argument("--feature_model", "-fm",
-	choices=["inception", "inception_tf", "resnet"]
-)
-
-parser.add_argument("--subset", "-sub",
-	help="Possible subsets: train, test",
-	choices=["train", "test"],
-	default="train", type=str)
-
-
-parser.add_argument("--start", "-s",
-	help="Image id to start with",
-	type=int, default=0)
-
-parser.add_argument("--n_images", "-n",
-	help="Number of images to display",
-	type=int, default=10)
-
-
-
-parser.add_argument("--rnd",
-	help="select random subset of present parts",
-	action="store_true")
-
-parser.add_argument("--crop_to_bb",
-	help="Crop image to the bounding box",
-	action="store_true")
-
-parser.add_argument("--crop_uniform",
-	help="Try to extend the bounding box to same height and width",
-	action="store_true")
-
-parser.add_argument("--parts_in_bb",
-	help="Only display parts, that are inside the bounding box",
-	action="store_true")
-
-
-
-parser.add_argument(
-	'--logfile', type=str, default='',
-	help='File for logging output')
-
-parser.add_argument(
-	'--loglevel', type=str, default='INFO',
-	help='logging level. see logging module for more information')
-
-parser.add_argument(
-	'--seed', type=int, default=12311123,
-	help='random seed')
-
-main(parser.parse_args())

+ 23 - 0
scripts/utils/__init__.py

@@ -0,0 +1,23 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+
+def plot_crops(crops, title, scatter_mid=False, names=None):
+
+	n_crops = crops.shape[0]
+	rows = int(np.ceil(np.sqrt(n_crops)))
+	cols = int(np.ceil(n_crops / rows))
+
+	fig, axs = plt.subplots(rows, cols, figsize=(16,9))
+	fig.suptitle(title, fontsize=16)
+	for i, crop in enumerate(crops):
+		ax = axs[np.unravel_index(i, axs.shape)]
+		if names is not None:
+			ax.set_title(names[i])
+		ax.imshow(crop)
+		ax.axis("off")
+		if scatter_mid:
+			middle_h, middle_w = crop.shape[0] / 2, crop.shape[1] / 2
+			ax.scatter(middle_w, middle_h, marker="x")
+
+

+ 81 - 0
scripts/utils/parser.py

@@ -0,0 +1,81 @@
+from cvargparse import BaseParser, Arg
+
+from nabirds.annotations import AnnotationType
+
+def parse_args():
+
+	parser = BaseParser([
+
+		Arg("data",
+			help="Folder containing the dataset with images and annotation files or dataset info file",
+			type=str),
+
+		AnnotationType.as_arg("dataset",
+			help_text="Type of the annotation"),
+
+		Arg("--parts", "-p",
+			choices=["GT", "GT2", "NAC", "UNI", "L1_pred", "L1_full"]),
+
+
+		Arg("--feature_model", "-fm",
+			choices=["inception", "inception_tf", "resnet"]),
+
+
+		Arg("--subset", "-sub",
+			help="Possible subsets: train, test",
+			choices=["train", "test"],
+			default="train", type=str),
+
+
+		Arg("--start", "-s",
+			help="Image id to start with",
+			type=int, default=0),
+
+		Arg("--n_images", "-n",
+			help="Number of images to display",
+			type=int, default=10),
+
+
+		Arg("--rnd",
+			help="select random subset of present parts",
+			action="store_true"),
+
+		Arg("--crop_to_bb",
+			help="Crop image to the bounding box",
+			action="store_true"),
+
+		Arg("--crop_uniform",
+			help="Try to extend the bounding box to same height and width",
+			action="store_true"),
+
+		Arg("--parts_in_bb",
+			help="Only display parts, that are inside the bounding box",
+			action="store_true"),
+
+
+		Arg("--features",
+			help="pre-extracted train and test features",
+			default=[None, None],
+			nargs=2, type=str),
+
+
+		Arg("--ratio",
+			help="Part extraction ratio",
+			type=float, default=.2),
+
+		Arg("--rescale_size",
+			help="rescales the part positions from this size to original image size",
+			type=int, default=-1),
+
+		Arg("--uniform_parts", "-u",
+			help="Do not use GT parts, but sample parts uniformly from the image",
+			action="store_true"),
+
+
+		Arg('--seed', type=int, default=12311123,
+			help='random seed'),
+
+	])
+
+	parser.init_logger()
+	return parser.parse_args()