Commit 7b893ab8 authored by Philip ABBET's avatar Philip ABBET

Add xm2vts/3 (api change: beat.backend.python v1.4.2)

parent eb16d51a
{
"description": "The XM2VTS Database of Faces",
"root_folder": "/idiap/resource/database/xm2vtsdb/images",
"protocols": [
{
"name": "lp1",
"template": "advanced_face_recognition",
"sets": [
{
"name": "train",
"template": "train",
"view": "Train",
"parameters": {
"protocol": "lp1"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "dev_templates",
"template": "templates",
"view": "Templates",
"parameters": {
"protocol": "lp1",
"group": "dev"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "dev_probes",
"template": "probes",
"view": "Probes",
"parameters": {
"protocol": "lp1",
"group": "dev"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"probe_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_ids": "{{ system_user.username }}/array_1d_uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "test_templates",
"template": "templates",
"view": "Templates",
"parameters": {
"protocol": "lp1",
"group": "eval"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "test_probes",
"template": "probes",
"view": "Probes",
"parameters": {
"protocol": "lp1",
"group": "eval"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"probe_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_ids": "{{ system_user.username }}/array_1d_uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
}
]
},
{
"name": "lp2",
"template": "advanced_face_recognition",
"sets": [
{
"name": "train",
"template": "train",
"view": "Train",
"parameters": {
"protocol": "lp2"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "dev_templates",
"template": "templates",
"view": "Templates",
"parameters": {
"protocol": "lp2",
"group": "dev"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "dev_probes",
"template": "probes",
"view": "Probes",
"parameters": {
"protocol": "lp2",
"group": "dev"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"probe_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_ids": "{{ system_user.username }}/array_1d_uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "test_templates",
"template": "templates",
"view": "Templates",
"parameters": {
"protocol": "lp2",
"group": "eval"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "test_probes",
"template": "probes",
"view": "Probes",
"parameters": {
"protocol": "lp2",
"group": "eval"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"probe_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_ids": "{{ system_user.username }}/array_1d_uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
}
]
},
{
"name": "darkened-lp1",
"template": "advanced_face_recognition",
"sets": [
{
"name": "train",
"template": "train",
"view": "Train",
"parameters": {
"protocol": "darkened-lp1"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "dev_templates",
"template": "templates",
"view": "Templates",
"parameters": {
"protocol": "darkened-lp1",
"group": "dev"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "dev_probes",
"template": "probes",
"view": "Probes",
"parameters": {
"protocol": "darkened-lp1",
"group": "dev"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"probe_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_ids": "{{ system_user.username }}/array_1d_uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "test_templates",
"template": "templates",
"view": "Templates",
"parameters": {
"protocol": "darkened-lp1",
"group": "eval"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "test_probes",
"template": "probes",
"view": "Probes",
"parameters": {
"protocol": "darkened-lp1",
"group": "eval"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"probe_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_ids": "{{ system_user.username }}/array_1d_uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
}
]
},
{
"name": "darkened-lp2",
"template": "advanced_face_recognition",
"sets": [
{
"name": "train",
"template": "train",
"view": "Train",
"parameters": {
"protocol": "darkened-lp2"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "dev_templates",
"template": "templates",
"view": "Templates",
"parameters": {
"protocol": "darkened-lp2",
"group": "dev"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "dev_probes",
"template": "probes",
"view": "Probes",
"parameters": {
"protocol": "darkened-lp2",
"group": "dev"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"probe_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_ids": "{{ system_user.username }}/array_1d_uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "test_templates",
"template": "templates",
"view": "Templates",
"parameters": {
"protocol": "darkened-lp2",
"group": "eval"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_id": "{{ system_user.username }}/uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
},
{
"name": "test_probes",
"template": "probes",
"view": "Probes",
"parameters": {
"protocol": "darkened-lp2",
"group": "eval"
},
"outputs": {
"file_id": "{{ system_user.username }}/uint64/1",
"probe_id": "{{ system_user.username }}/uint64/1",
"client_id": "{{ system_user.username }}/uint64/1",
"template_ids": "{{ system_user.username }}/array_1d_uint64/1",
"image": "{{ system_user.username }}/array_3d_uint8/1",
"eye_centers": "{{ system_user.username }}/eye_positions/1"
}
}
]
}
]
}
###############################################################################
# #
# Copyright (c) 2017 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 numpy as np
import bob.io.base
import bob.io.image
import bob.db.xm2vts
#----------------------------------------------------------
def get_client_end_index(objs, client_id, client_start_index,
start_index, end_index):
client_end_index = client_start_index
while client_end_index + 1 <= end_index:
obj = objs[client_end_index + 1 - start_index]
if isinstance(obj, tuple):
obj = obj[1]
if obj.client_id != client_id:
return client_end_index
client_end_index += 1
return end_index
#----------------------------------------------------------
def get_value_end_index(objs, value, index_in_tuple, value_start_index,
start_index, end_index):
value_end_index = value_start_index
while value_end_index + 1 <= end_index:
id = objs[value_end_index + 1 - start_index][index_in_tuple]
if id != value:
return value_end_index
value_end_index += 1
return end_index
#----------------------------------------------------------
class Train:
"""Outputs:
- image: "{{ system_user.username }}/array_3d_uint8/1"
- file_id: "{{ system_user.username }}/uint64/1"
- eye_centers: "{{ system_user.username }}/eye_positions/1"
- client_id: "{{ system_user.username }}/uint64/1"
One "file_id" is associated with a given "image".
One "eye_centers" is associated with a given "image".
Several "image" are associated with a given "client_id".
--------------- --------------- --------------- --------------- --------------- ---------------
| image | | image | | image | | image | | image | | image |
--------------- --------------- --------------- --------------- --------------- ---------------
--------------- --------------- --------------- --------------- --------------- ---------------
| file_id | | file_id | | file_id | | file_id | | file_id | | file_id |
--------------- --------------- --------------- --------------- --------------- ---------------
--------------- --------------- --------------- --------------- --------------- ---------------
| eye_centers | | eye_centers | | eye_centers | | eye_centers | | eye_centers | | eye_centers |
--------------- --------------- --------------- --------------- --------------- ---------------
----------------------------------------------- -----------------------------------------------
| client_id | | client_id |
----------------------------------------------- -----------------------------------------------
"""
def setup(self, root_folder, outputs, parameters, force_start_index=None,
force_end_index=None):
# Initialisations
self.root_folder = root_folder
self.outputs = outputs
self.parameters = parameters
# Open the database and load the objects to provide via the outputs
self.db = bob.db.xm2vts.Database()
self.objs = sorted(self.db.objects(protocol=parameters['protocol'],
groups='world'),
key=lambda x: (x.client_id, x.id))
# Determine the range of indices that must be provided
self.start_index = force_start_index if force_start_index is not None else 0
self.end_index = force_end_index if force_end_index is not None else len(self.objs) - 1
self.objs = self.objs[self.start_index : self.end_index + 1]
self.next_index = self.start_index
return True
def done(self, last_data_index):
return last_data_index >= self.end_index
def next(self):
obj = self.objs[self.next_index - self.start_index]
# Output: client_id (only provide data when the client_id change)
if self.outputs['client_id'].isConnected() and \
self.outputs['client_id'].last_written_data_index < self.next_index:
client_end_index = get_client_end_index(self.objs, obj.client_id,
self.next_index,
self.start_index,
self.end_index)
self.outputs['client_id'].write(
{
'value': np.uint64(obj.client_id)
},
client_end_index
)
# Output: file_id (provide data at each iteration)
if self.outputs['file_id'].isConnected():
self.outputs['file_id'].write(
{
'value': np.uint64(obj.id)
},
self.next_index
)
# Output: image (provide data at each iteration)
if self.outputs['image'].isConnected():
self.outputs['image'].write(
{
'value': bob.io.base.load(obj.make_path(self.root_folder, '.ppm'))
},
self.next_index
)
# Output: eye_centers (provide data at each iteration)
if self.outputs['eye_centers'].isConnected():
annotation = self.db.annotations(obj)
self.outputs['eye_centers'].write({
'left': {
'y': np.int32(annotation['leye'][0]),
'x': np.int32(annotation['leye'][1]),
},
'right': {
'y': np.int32(annotation['reye'][0]),
'x': np.int32(annotation['reye'][1]),
}
},
self.next_index
)
# Determine the next data index that must be provided
self.next_index = 1 + min([ x.last_written_data_index for x in self.outputs
if x.isConnected() ]
)
return True
#----------------------------------------------------------
class Templates:
"""Outputs:
- image: "{{ system_user.username }}/array_3d_uint8/1"
- file_id: "{{ system_user.username }}/uint64/1"
- eye_centers: "{{ system_user.username }}/eye_positions/1"
- template_id: "{{ system_user.username }}/uint64/1"
- client_id: "{{ system_user.username }}/uint64/1"
One "file_id" is associated with a given "image".
One "eye_centers" is associated with a given "image".
Several "image" are associated with a given "template_id".
Several "template_id" are associated with a given "client_id".
--------------- --------------- --------------- --------------- --------------- ---------------
| image | | image | | image | | image | | image | | image |
--------------- --------------- --------------- --------------- --------------- ---------------
--------------- --------------- --------------- --------------- --------------- ---------------
| file_id | | file_id | | file_id | | file_id | | file_id | | file_id |
--------------- --------------- --------------- --------------- --------------- ---------------
--------------- --------------- --------------- --------------- --------------- ---------------
| eye_centers | | eye_centers | | eye_centers | | eye_centers | | eye_centers | | eye_centers |
--------------- --------------- --------------- --------------- --------------- ---------------
----------------------------------------------- -----------------------------------------------
| template_id | | template_id |
----------------------------------------------- -----------------------------------------------
-----------------------------------------------------------------------------------------------
| client_id |
-----------------------------------------------------------------------------------------------
Note: for this particular database, there is only one "template_id"
per "client_id".
"""
def setup(self, root_folder, outputs, parameters, force_start_index=None,
force_end_index=None):
# Initialisations
self.root_folder = root_folder
self.outputs = outputs
self.parameters = parameters
# Open the database and load the objects to provide via the outputs
self.db = bob.db.xm2vts.Database()
template_ids = self.db.model_ids(protocol=parameters['protocol'],
groups=parameters['group'])
self.objs = []
for template_id in template_ids:
objs = self.db.objects(protocol=parameters['protocol'],
groups=parameters['group'],
purposes='enroll',
model_ids=[template_id])
self.objs.extend([ (template_id, obj) for obj in objs ])
self.objs = sorted(self.objs, key=lambda x: (x[1].client_id, x[0], x[1].id))
# Determine the range of indices that must be provided
self.start_index = force_start_index if force_start_index is not None else 0
self.end_index = force_end_index if force_end_index is not None else len(self.objs) - 1
self.objs = self.objs[self.start_index : self.end_index + 1]
self.next_index = self.start_index
return True
def done(self, last_data_index):
return last_data_index >= self.end_index
def next(self):
(template_id, obj) = self.objs[self.next_index - self.start_index]
# Output: template_id (only provide data when the template_id change)
if self.outputs['template_id'].isConnected() and \
self.outputs['template_id'].last_written_data_index < self.next_index:
template_end_index = get_value_end_index(self.objs, template_id, 0,
self.next_index,
self.start_index,
self.end_index)
self.outputs['template_id'].write(
{
'value': np.uint64(template_id)
},
template_end_index
)
# Output: client_id (only provide data when the client_id change)
if self.outputs['client_id'].isConnected() and \
self.outputs['client_id'].last_written_data_index < self.next_index:
client_end_index = get_client_end_index(self.objs, obj.client_id,
self.next_index,
self.start_index,
self.end_index)
self.outputs['client_id'].write(
{
'value': np.uint64(obj.client_id)
},
client_end_index
)
# Output: file_id (provide data at each iteration)
if self.outputs['file_id'].isConnected():
self.outputs['file_id'].write(
{
'value': np.uint64(obj.id)
},
self.next_index
)
# Output: image (provide data at each iteration)
if self.outputs['image'].isConnected():
self.outputs['image'].write(
{
'value': bob.io.base.load(obj.make_path(self.root_folder, '.ppm'))
},
self.next_index
)
# Output: eye_centers (provide data at each iteration)
if self.outputs['eye_centers'].isConnected():
annotation = self.db.annotations(obj)
self.outputs['eye_centers'].write({
'left': {
'y': np.int32(annotation['leye'][0]),
'x': np.int32(annotation['leye'][1]),
},
'right': {
'y': np.int32(annotation['reye'][0]),
'x': np.int32(annotation['reye'][1]),
}
},
self.next_index
)
# Determine the next data index that must be provided
self.next_index = 1 + min([ x.last_written_data_index for x in self.outputs
if x.isConnected() ]
)
return True
#----------------------------------------------------------
class Probes:
"""Outputs:
- image: "{{ system_user.username }}/array_3d_uint8/1"
- file_id: "{{ system_user.username }}/uint64/1"
- eye_centers: "{{ system_user.username }}/eye_positions/1"
- probe_id: "{{ system_user.username }}/uint64/1"
- client_id: "{{ system_user.username }}/uint64/1"
- template_ids: "{{ system_user.username }}/array_1d_uint64/1"
One "file_id" is associated with a given "image".