diff --git a/advanced/databases/biowave/4.json b/advanced/databases/biowave/4.json new file mode 100644 index 0000000000000000000000000000000000000000..a928cf223eff9c17d0a9b7e1a1ee90a649ddcdcf --- /dev/null +++ b/advanced/databases/biowave/4.json @@ -0,0 +1,874 @@ +{ + "root_folder": "/idiap/project/biowave/biowave_v1/data", + "description": "BIOWAVE Vein Database", + "protocols": [ + { + "name": "Idiap_1_1_R_BEAT_test", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_5_5_R_BEAT_test", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_5_R_BEAT_test", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R_BEAT_test", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_5_R_BEAT_test", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R_BEAT_test", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_5_R_BEAT_test", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R_BEAT_test", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_1_R", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_5_R", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_5_R", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_5_R", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_3_5_R", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_3_5_R", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_3_5_R", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_3_5_R", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_3_5_R", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_3_5_R", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_5_5_R", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_1_L", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_5_L", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_L", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_5_L", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_L", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_5_L", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_L", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_5_5_L", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_1_R_less", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R_less", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_1_R_less", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R_less", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_1_R_less", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_1_R_less", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_5_R_less", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R_less", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_5_R_less", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R_less", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_1_5_R_less", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_1_5_R_less", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_5_5_R_less", + "template": "advanced_vein_recognition_2/1", + "views": { + "train": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R_less", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_5_5_R_less", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R_less", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateView", + "parameters": { + "protocol": "Idiap_5_5_R_less", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "View", + "parameters": { + "protocol": "Idiap_5_5_R_less", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_1_R_annotations_BEAT_test", + "template": "advanced_vein_annotations/1", + "views": { + "train": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R_BEAT_test", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_2_1_R_annotations_BEAT_test", + "template": "advanced_vein_annotations/1", + "views": { + "train": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R_BEAT_test", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_1_R_annotations", + "template": "advanced_vein_annotations/1", + "views": { + "train": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_R", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_2_1_R_annotations", + "template": "advanced_vein_annotations/1", + "views": { + "train": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_R", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_1_1_L_annotations", + "template": "advanced_vein_annotations/1", + "views": { + "train": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_1_1_L", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "Idiap_2_1_L_annotations", + "template": "advanced_vein_annotations/1", + "views": { + "train": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "world" + } + }, + "dev_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "dev", + "purpose": "enroll" + } + }, + "dev_probes": { + "view": "ViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "dev", + "purpose": "probe" + } + }, + "eval_templates": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "eval", + "purpose": "enroll" + } + }, + "eval_probes": { + "view": "TemplateViewAnnotations", + "parameters": { + "protocol": "Idiap_5_5_L", + "group": "eval", + "purpose": "probe" + } + } + } + }, + { + "name": "annotation_benchmark", + "template": "advanced_annotation_benchmark/1", + "views": { + "annotations": { + "view": "AnnotationBenchmark", + "parameters": { + "protocol": "Idiap_1_1_R" + } + } + } + } + ], + "schema_version": 2 +} \ No newline at end of file diff --git a/advanced/databases/biowave/4.py b/advanced/databases/biowave/4.py new file mode 100644 index 0000000000000000000000000000000000000000..fa4837a641853c28b2e4ca8197743c88ad04bd60 --- /dev/null +++ b/advanced/databases/biowave/4.py @@ -0,0 +1,497 @@ +############################################################################### +# # +# Copyright (c) 2018 Idiap Research Institute, http://www.idiap.ch/ # +# Contact: beat.support@idiap.ch # +# # +# This file is part of the beat.examples module of the BEAT platform. # +# # +# Commercial License Usage # +# Licensees holding valid commercial BEAT licenses may use this file in # +# accordance with the terms contained in a written agreement between you # +# and Idiap. For further information contact tto@idiap.ch # +# # +# Alternatively, this file may be used under the terms of the GNU Affero # +# Public License version 3 as published by the Free Software and appearing # +# in the file LICENSE.AGPL included in the packaging of this file. # +# The BEAT platform is distributed in the hope that it will be useful, but # +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # +# or FITNESS FOR A PARTICULAR PURPOSE. # +# # +# You should have received a copy of the GNU Affero Public License along # +# with the BEAT platform. If not, see http://www.gnu.org/licenses/. # +# # +############################################################################### + +import os +import numpy as np +from collections import namedtuple + +from beat.backend.python.database import View as BaseView + +import bob.io.base +import bob.io.image +import bob.db.biowave_v1 + +from PIL import Image, ImageDraw, ImageFilter + + +#---------------------------------------------------------- + + +def construct_ROI_image(annotations): + """Adapted from bob.db.biowave_v1, because we want to separate it in two steps: + indexing and image construction""" + + if len(annotations) > 0: + return bob.db.biowave_v1.utils.ManualRoiCut(annotations).roi_mask() + else: + return np.array([], np.uint8) + + +#---------------------------------------------------------- + + +def construct_vein_image(annotations, center=False): + """Adapted from bob.db.biowave_v1, because we want to separate it in two steps: + indexing and image construction""" + + if len(annotations) > 0: + im = Image.new('L', (480, 480), (0)) + draw = ImageDraw.Draw(im) + if center: + xes_all = [point[1] for line in annotations for point in line] + yes_all = [point[0] for line in annotations for point in line] + for line in annotations: + xes = [point[1] - np.round(np.mean(xes_all)) + 239 for point in line] + yes = [point[0] - np.round(np.mean(yes_all)) + 239 for point in line] + for point in range(len(line) - 1): + draw.line((xes[point],yes[point], xes[point+1], yes[point+1]), fill=255, width = 5) + else: + for line in annotations: + xes = [point[1] for point in line] + yes = [point[0] for point in line] + for point in range(len(line) - 1): + draw.line((xes[point],yes[point], xes[point+1], yes[point+1]), fill=255, width = 5) + im = im.filter(ImageFilter.MedianFilter(5)) + return np.array(np.array(im, dtype = bool), dtype = np.uint8) + else: + return np.array([], np.uint8) + + +#---------------------------------------------------------- + + +def construct_alignment_annotations(annotations): + return [ dict( + x = np.int32(annotation[1]), + y = np.int32(annotation[0]) + ) for annotation in annotations ] + + +#---------------------------------------------------------- + + +class View(BaseView): + """Outputs: + - image: "{{ system_user.username }}/array_2d_uint8/1" + - client_id: "{{ system_user.username }}/uint64/1" + + Several "image" are associated with a given "client_id". + + --------------- --------------- --------------- --------------- --------------- --------------- + | image | | image | | image | | image | | image | | image | + --------------- --------------- --------------- --------------- --------------- --------------- + ----------------------------------------------- ----------------------------------------------- + | client_id | | client_id | + ----------------------------------------------- ----------------------------------------------- + """ + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['client_id', 'image']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.biowave_v1.Database() + + objs = sorted(db.objects(protocol=parameters['protocol'], + groups=[parameters['group']], + purposes=parameters.get('purpose', None), + annotated_images=False, + imagedir=root_folder), + key=lambda x: (x.client_id, x.id)) + + return [ Entry(x.client_id, x.make_path(root_folder, '.png')) for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'client_id': + return { + 'value': np.uint64(obj.client_id) + } + + elif output == 'image': + return { + 'value': bob.io.base.load(obj.image) + } + + +#---------------------------------------------------------- + + +class TemplateView(BaseView): + """Outputs: + - image: "{{ system_user.username }}/array_2d_uint8/1" + - model_id: "{{ system_user.username }}/text/1" + - client_id: "{{ system_user.username }}/uint64/1" + + Several "image" are associated with a given "model_id". + Several "model_id" are associated with a given "client_id". + + --------------- --------------- --------------- --------------- --------------- --------------- + | image | | image | | image | | image | | image | | image | + --------------- --------------- --------------- --------------- --------------- --------------- + ----------------------------------------------- ----------------------------------------------- + | model_id | | model_id | + ----------------------------------------------- ----------------------------------------------- + ----------------------------------------------------------------------------------------------- + | client_id | + ----------------------------------------------------------------------------------------------- + + Note: for this particular database, there is only one "image" + per "model_id". + """ + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['client_id', 'model_id', 'image']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.biowave_v1.Database() + + objs = sorted(db.objects(protocol=parameters['protocol'], + purposes=parameters['purpose'], + groups=[parameters['group']], + annotated_images=False, + imagedir=root_folder), + key=lambda x: (x.client_id, x.id)) + + return [ Entry(x.client_id, x.model_id.encode('utf-8'), + x.make_path(root_folder, '.png')) + for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'client_id': + return { + 'value': np.uint64(obj.client_id) + } + + elif output == 'model_id': + return { + 'text': str(obj.model_id) + } + + elif output == 'image': + return { + 'value': bob.io.base.load(obj.image) + } + + +#---------------------------------------------------------- + + +class ViewAnnotations(BaseView): + """Outputs: + - image: "{{ system_user.username }}/array_2d_uint8/1" + - vein_annotations: "{{ system_user.username }}/array_2d_uint8/1" + - ROI_annotations: "{{ system_user.username }}/array_2d_uint8/1" + - alignment_annotations: "{{ system_user.username }}/array_1d_coordinates/1" + - client_id: "{{ system_user.username }}/uint64/1" + + One "vein_annotations" are associated with a given "image". + One "ROI_annotations" are associated with a given "image". + One "alignment_annotations" are associated with a given "image". + Several "image" are associated with a given "client_id". + + ------------------------- ------------------------- ------------------------- ------------------------- + | image | | image | | image | | image | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | vein_annotations | | vein_annotations | | vein_annotations | | vein_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | ROI_annotations | | ROI_annotations | | ROI_annotations | | ROI_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | alignment_annotations | | alignment_annotations | | alignment_annotations | | alignment_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + --------------------------------------------------- --------------------------------------------------- + | client_id | | client_id | + --------------------------------------------------- --------------------------------------------------- + """ + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['client_id', 'alignment_annotations', 'ROI_annotations', + 'vein_annotations', 'image']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.biowave_v1.Database() + + objs = sorted(db.objects(protocol=parameters['protocol'], + groups=[parameters['group']], + purposes=parameters.get('purpose', None), + annotated_images=True, + imagedir=root_folder), + key=lambda x: (x.client_id, x.id)) + + return [ Entry(x.client_id, + x.alignment_annotations(directory=root_folder), + x.roi_annotations(directory=root_folder), + x.vein_annotations(directory=root_folder), + x.make_path(root_folder, '.png')) + for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'client_id': + return { + 'value': np.uint64(obj.client_id) + } + + elif output == 'alignment_annotations': + return { + 'value': construct_alignment_annotations(obj.alignment_annotations) + } + + elif output == 'ROI_annotations': + return { + 'value': construct_ROI_image(obj.ROI_annotations) + } + + elif output == 'vein_annotations': + return { + 'value': construct_vein_image(obj.vein_annotations) + } + + elif output == 'image': + return { + 'value': bob.io.base.load(obj.image) + } + + +#---------------------------------------------------------- + + +class TemplateViewAnnotations(BaseView): + """Outputs: + - image: "{{ system_user.username }}/array_2d_uint8/1" + - vein_annotations: "{{ system_user.username }}/array_2d_uint8/1" + - ROI_annotations: "{{ system_user.username }}/array_2d_uint8/1" + - alignment_annotations: "{{ system_user.username }}/array_1d_coordinates/1" + - model_id: "{{ system_user.username }}/model_id/1" + - client_id: "{{ system_user.username }}/uint64/1" + + One "vein_annotations" are associated with a given "image". + One "ROI_annotations" are associated with a given "image". + One "alignment_annotations" are associated with a given "image". + Several "image" are associated with a given "model_id". + Several "model_id" are associated with a given "client_id". + + ------------------------- ------------------------- ------------------------- ------------------------- + | image | | image | | image | | image | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | vein_annotations | | vein_annotations | | vein_annotations | | vein_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | ROI_annotations | | ROI_annotations | | ROI_annotations | | ROI_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | alignment_annotations | | alignment_annotations | | alignment_annotations | | alignment_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + --------------------------------------------------- --------------------------------------------------- + | model_id | | model_id | + --------------------------------------------------- --------------------------------------------------- + ------------------------------------------------------------------------------------------------------- + | client_id | + ------------------------------------------------------------------------------------------------------- + + Note: for this particular database, there is only one "image" + per "model_id". + """ + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['client_id', 'model_id', 'alignment_annotations', + 'ROI_annotations', 'vein_annotations', 'image']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.biowave_v1.Database() + + objs = sorted(db.objects(protocol=parameters['protocol'], + groups=[parameters['group']], + purposes=parameters['purpose'], + annotated_images=True, + imagedir=root_folder), + key=lambda x: (x.client_id, x.model_id, x.id)) + + return [ Entry(x.client_id, + x.model_id.encode('utf-8'), + x.alignment_annotations(directory=root_folder), + x.roi_annotations(directory=root_folder), + x.vein_annotations(directory=root_folder), + x.make_path(root_folder, '.png')) + for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'client_id': + return { + 'value': np.uint64(obj.client_id) + } + + elif output == 'model_id': + return { + 'text': obj.model_id + } + + elif output == 'alignment_annotations': + return { + 'value': construct_alignment_annotations(obj.alignment_annotations) + } + + elif output == 'ROI_annotations': + return { + 'value': construct_ROI_image(obj.ROI_annotations) + } + + elif output == 'vein_annotations': + return { + 'value': construct_vein_image(obj.vein_annotations) + } + + elif output == 'image': + return { + 'value': bob.io.base.load(obj.image) + } + + +#---------------------------------------------------------- + + +class AnnotationBenchmark(BaseView): + """Outputs: + - image: "{{ system_user.username }}/array_2d_uint8/1" + - vein_annotations: "{{ system_user.username }}/array_2d_uint8/1" + - ROI_annotations: "{{ system_user.username }}/array_2d_uint8/1" + - alignment_annotations: "{{ system_user.username }}/array_1d_coordinates/1" + + One "vein_annotations" are associated with a given "image". + One "ROI_annotations" are associated with a given "image". + One "alignment_annotations" are associated with a given "image". + + ------------------------- ------------------------- ------------------------- ------------------------- + | image | | image | | image | | image | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | vein_annotations | | vein_annotations | | vein_annotations | | vein_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | ROI_annotations | | ROI_annotations | | ROI_annotations | | ROI_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + ------------------------- ------------------------- ------------------------- ------------------------- + | alignment_annotations | | alignment_annotations | | alignment_annotations | | alignment_annotations | + ------------------------- ------------------------- ------------------------- ------------------------- + """ + + def index(self, root_folder, parameters): + Entry = namedtuple('Entry', ['alignment_annotations', 'ROI_annotations', + 'vein_annotations', 'image']) + + # Open the database and load the objects to provide via the outputs + db = bob.db.biowave_v1.Database() + + objs = sorted(db.objects(protocol=parameters['protocol'], + annotated_images=True, + imagedir=root_folder), + key=lambda x: x.id) + + return [ Entry(x.alignment_annotations(directory=root_folder), + x.roi_annotations(directory=root_folder), + x.vein_annotations(directory=root_folder), + x.make_path(root_folder, '.png')) + for x in objs ] + + + def get(self, output, index): + obj = self.objs[index] + + if output == 'alignment_annotations': + return { + 'value': construct_alignment_annotations(obj.alignment_annotations) + } + + elif output == 'ROI_annotations': + return { + 'value': construct_ROI_image(obj.ROI_annotations) + } + + elif output == 'vein_annotations': + return { + 'value': construct_vein_image(obj.vein_annotations) + } + + elif output == 'image': + return { + 'value': bob.io.base.load(obj.image) + } + + +#---------------------------------------------------------- + + +def setup_tests(): + # Install a mock methods + def mock_load(root_folder): + return np.ndarray((10, 20), dtype=np.uint8) + + bob.io.base.load = mock_load + + +#---------------------------------------------------------- + + +# Test the behavior of the views (on fake data) +if __name__ == '__main__': + + setup_tests() + + view = View() + view.objs = view.index( + root_folder='', + parameters=dict( + protocol="Idiap_1_1_R_BEAT_test", + group="world", + ) + ) + view.get('client_id', 0) + view.get('image', 0) + + + view = TemplateView() + view.objs = view.index( + root_folder='', + parameters=dict( + protocol="Idiap_1_1_R_BEAT_test", + group="dev", + purpose="enroll", + ) + ) + view.get('client_id', 0) + view.get('model_id', 0) + view.get('image', 0) diff --git a/advanced/databases/biowave/4.rst b/advanced/databases/biowave/4.rst new file mode 100644 index 0000000000000000000000000000000000000000..67429868f7d24aa105e309da653dea9a24c0ffbd --- /dev/null +++ b/advanced/databases/biowave/4.rst @@ -0,0 +1 @@ +BIOWAVE Vein Database \ No newline at end of file