Commit fde5c50f authored by Guillaume HEUSCH's avatar Guillaume HEUSCH
Browse files

Merge branch 'cleaning' into 'master'

Cleaning

See merge request bob/bob.db.fargo!4
parents c55af829 283c3379
# This build file uses template features from YAML so it is generic enough for
# any Bob project. Don't modify it unless you know what you're doing.
# Definition of global variables (all stages)
variables:
CONDA_ROOT: "${CI_PROJECT_DIR}/miniconda"
# Definition of our build pipeline order
stages:
- build
- deploy
- pypi
# Build targets
.build_template: &build_job
stage: build
before_script:
- mkdir _ci
- curl --silent "https://gitlab.idiap.ch/bob/bob.admin/raw/master/gitlab/install.sh" > _ci/install.sh
- chmod 755 _ci/install.sh
- ./_ci/install.sh _ci master #installs ci support scripts
- ./_ci/before_build.sh
script:
- ./_ci/build.sh
after_script:
- ./_ci/after_build.sh
cache: &build_caches
paths:
- miniconda.sh
- ${CONDA_ROOT}/pkgs/*.tar.bz2
- ${CONDA_ROOT}/pkgs/urls.txt
.build_linux_template: &linux_build_job
<<: *build_job
tags:
- docker
image: continuumio/conda-concourse-ci
artifacts:
expire_in: 1 week
paths:
- _ci/
- ${CONDA_ROOT}/conda-bld/linux-64/*.tar.bz2
cache:
<<: *build_caches
key: "linux-cache"
.build_macosx_template: &macosx_build_job
<<: *build_job
tags:
- macosx
artifacts:
expire_in: 1 week
paths:
- _ci/
- ${CONDA_ROOT}/conda-bld/osx-64/*.tar.bz2
cache:
<<: *build_caches
key: "macosx-cache"
build_linux_36:
<<: *linux_build_job
variables:
PYTHON_VERSION: "3.6"
BUILD_EGG: "true"
artifacts:
expire_in: 1 week
paths:
- _ci/
- dist/*.zip
- sphinx
- ${CONDA_ROOT}/conda-bld/linux-64/*.tar.bz2
build_macosx_36:
<<: *macosx_build_job
variables:
PYTHON_VERSION: "3.6"
# Deploy targets
.deploy_template: &deploy_job
stage: deploy
before_script:
- ./_ci/install.sh _ci master #updates ci support scripts
script:
- ./_ci/deploy.sh
dependencies:
- build_linux_36
- build_macosx_36
tags:
- deployer
deploy_beta:
<<: *deploy_job
environment: beta
only:
- master
deploy_stable:
<<: *deploy_job
environment: stable
only:
- /^v\d+\.\d+\.\d+([abc]\d*)?$/ # PEP-440 compliant version (tags)
except:
- branches
pypi:
stage: pypi
environment: pypi
only:
- /^v\d+\.\d+\.\d+([abc]\d*)?$/ # PEP-440 compliant version (tags)
except:
- branches
before_script:
- ./_ci/install.sh _ci master #updates ci support scripts
script:
- ./_ci/pypi.sh
dependencies:
- build_linux_36
tags:
- deployer
include: 'https://gitlab.idiap.ch/bob/bob.devtools/raw/master/bob/devtools/data/gitlab-ci/single-package.yaml'
#!/usr/bin/env python
# encoding: utf-8
from .query import Database
import bob.io.image
#from bob.bio.base.database.filelist.models import FileListFile, Client
#from bob.bio.base.database.filelist.models import FileListFile
def get_config():
"""Returns a string containing the configuration information.
......@@ -13,6 +9,5 @@ def get_config():
import bob.extension
return bob.extension.get_config(__name__)
# gets sphinx autodoc done right - don't remove it
__all__ = [_ for _ in dir() if not _.startswith('_')]
import json
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
import json
import numpy as np
import cv2
#def depth_to_rgb(depth_frame, min_depth_value, max_depth_value,
# colormap=cv2.COLORMAP_HSV, range_min=None, range_max=None):
# """
#
# """
# valid_mask = cv2.inRange(depth_frame, min_depth_value, max_depth_value)
# if range_min is None or range_max is None:
# range_min, range_max, _, _ = cv2.minMaxLoc(depth_frame, valid_mask)
# if range_max != range_min:
# scale = np.iinfo(np.uint8).max / (range_max - range_min)
# else:
# scale = 1.0
# depth_frame_view = cv2.convertScaleAbs(depth_frame, alpha=scale,
# beta=-scale * range_min)
# return cv2.applyColorMap(depth_frame_view, colormap)
def points_to_color(points, intrinsics):
x = points[0] / points[2]
......
......@@ -6,7 +6,6 @@ from .models import *
from bob.db.base.driver import Interface as BaseInterface
import bob.core
logger = bob.core.log.setup('bob.db.fargo')
......@@ -52,7 +51,6 @@ def add_files(session, imagesdir, extension='.png'):
The extension of the image file.
"""
for root, dirs, files in os.walk(imagesdir, topdown=False):
for name in files:
image_filename = os.path.join(root, name)
......
#!/usr/bin/env python
# encoding: utf-8
# Guillaume HEUSCH <guillaume.heusch@idiap.ch>
# Thu 22 Dec 16:23:51 CET 2016
"""Commands the FARGO database can respond to.
"""
......
#!/usr/bin/env python
# encoding: utf-8
# Guillaume HEUSCH <guillaume.heusch@idiap.ch>
# Mon 24 Apr 09:35:40 CEST 2017
""" Run face cropping on the FARGO database (%(version)s)
Usage:
%(prog)s --imagesdir=<path> --posdir=<path> --croppeddir=<path>
[--mod=<string>] [--protocol=<string>]
[--log=<string>] [--gridcount]
[--verbose ...] [--plot]
Options:
-h, --help Show this screen.
-V, --version Show version.
-i, --imagesdir=<path> Where the face images are stored.
-p, --posdir=<path> The position of the eyes.
-c, --croppeddir=<path> Where to store results.
--mod=<string> The modality (RGB or NIR) [default: RGB]
--protocol=<string> The protocol (MC, UD or UO) [default: MC].
-l, --log=<string> Log filename [default: log_face_detect.txt]
-G, --gridcount Display the number of objects and exits.
-v, --verbose Increase the verbosity (may appear multiple times).
-P, --plot Show some stuff
Example:
To run the face cropping process
$ %(prog)s --imagesdir path/to/database --posdir path/to/eyes --croppeddir path/to/cropped
See '%(prog)s --help' for more information.
"""
import os
import sys
import pkg_resources
import logging
__logging_format__='[%(levelname)s] %(message)s'
logging.basicConfig(format=__logging_format__)
logger = logging.getLogger("face_detect_log")
from docopt import docopt
version = pkg_resources.require('bob.db.fargo')[0].version
import numpy
import bob.io.base
import bob.io.image
import bob.bio.face
import bob.db.fargo
import bob.ip.facedetect
import bob.ip.draw
from bob.bio.face.preprocessor import FaceCrop
import gridtk
def main(user_input=None):
"""
Main function to crop faces in FARGO frontal images
"""
# Parse the command-line arguments
if user_input is not None:
arguments = user_input
else:
arguments = sys.argv[1:]
prog = os.path.basename(sys.argv[0])
completions = dict(prog=prog, version=version,)
args = docopt(__doc__ % completions,argv=arguments,version='Face cropping (%s)' % version,)
# if the user wants more verbosity, lowers the logging level
if args['--verbose'] == 1: logging.getLogger("face_detect_log").setLevel(logging.INFO)
elif args['--verbose'] >= 2: logging.getLogger("face_detect_log").setLevel(logging.DEBUG)
# log file to record errors ...
logfile = open(args['--log'], 'a')
# check user input
if not (args['--protocol'] == 'MC' or args['--protocol'] == 'UD' or args['--protocol'] == 'UO'):
logger.warning("Please provide a valid protocol name, {0} is not !".format(args['--protocol']))
sys.exit()
if not (args['--mod'] == 'RGB' or args['--mod'] == 'NIR'):
logger.warning("Please provide a valid modality, {0} is not !".format(args['--mod']))
sys.exit()
# get the modality and the channel
if args['--mod'] == 'RGB':
modality = 'RGB'
channel = 'color'
if args['--mod'] == 'NIR':
modality = 'NIR'
channel = 'ir'
db = bob.db.fargo.Database()
protocol = 'public_' + args['--protocol'] + '_' + args['--mod']
objs = db.objects(protocol=protocol, groups=['world', 'dev', 'eval'])
# if we are on a grid environment, just find what I have to process.
if os.environ.has_key('SGE_TASK_ID'):
pos = int(os.environ['SGE_TASK_ID']) - 1
if pos >= len(objs):
raise RuntimeError, "Grid request for job %d on a setup with %d jobs" % \
(pos, len(objs))
objs = [objs[pos]]
if args['--gridcount']:
print len(objs)
sys.exit()
# counters
image_counter = 0
# the face cropper
CROPPED_IMAGE_HEIGHT = 64
CROPPED_IMAGE_WIDTH = 64
RIGHT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 - 1)
LEFT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 * 3)
face_cropper = FaceCrop(cropped_image_size=(CROPPED_IMAGE_HEIGHT, CROPPED_IMAGE_WIDTH),
cropped_positions={'leye': LEFT_EYE_POS, 'reye': RIGHT_EYE_POS},
color_channel='rgb',
dtype='uint8'
)
# === LET'S GO ===
for image in objs:
filename = os.path.join(args['--imagesdir'], image.path)
filename += '.png'
pos_filename = os.path.join(args['--posdir'], image.path)
pos_filename += '.pos'
if not os.path.isfile(pos_filename):
logger.warn("pos file for {0} does not exists".format(image.path))
continue
logger.info("Cropping face in {0}".format(image.path))
face_image = bob.io.base.load(filename)
# load pos file
eyesfiles = open(pos_filename, 'r')
eyes = eyesfiles.readline()
reyex, reyey, leyex, leyey = eyes.split()
eyes={'reye' : (int(reyey), int(reyex)), 'leye' : (int(leyey), int(leyex))}
cropped = face_cropper(face_image, annotations=eyes)
if bool(args['--plot']):
from matplotlib import pyplot
pyplot.imshow(numpy.rollaxis(numpy.rollaxis(cropped, 2),2))
pyplot.show()
cropped_filename = os.path.join(args['--croppeddir'], image.path)
cropped_filename += '.png'
if not os.path.isdir(os.path.dirname(cropped_filename)):
os.makedirs(os.path.dirname(cropped_filename))
bob.io.base.save(cropped, cropped_filename)
image_counter += 1
logger.info("{0} faces were not detected (out of {1})".format(no_face_detected, image_counter))
logfile.close()
#!/usr/bin/env python
# encoding: utf-8
""" Run face detection on the FARGO database (%(version)s)
Usage:
%(prog)s --imagesdir=<path> --posdir=<path>
[--mod=<string>] [--protocol=<string>]
[--log=<string>] [--gridcount]
[--verbose ...] [--plot] [--facedetect=<string>]
Options:
-h, --help Show this screen.
-V, --version Show version.
-i, --imagesdir=<path> Where the face images are stored.
-p, --posdir=<path> Where to store results.
--mod=<string> The modality (RGB or NIR) [default: RGB]
--protocol=<string> The protocol (MC, UD or UO) [default: MC].
-l, --log=<string> Log filename [default: log_face_detect.txt]
-G, --gridcount Display the number of objects and exits.
-v, --verbose Increase the verbosity (may appear multiple times).
-P, --plot Show some stuff
--facedetect=<string> Face detection algorithm [default: bob]
Example:
To run the face detection process
$ %(prog)s --imagesdir path/to/database
See '%(prog)s --help' for more information.
"""
from __future__ import print_function
import os
import sys
import pkg_resources
import logging
__logging_format__='[%(levelname)s] %(message)s'
logging.basicConfig(format=__logging_format__)
logger = logging.getLogger("face_detect_log")
from docopt import docopt
version = pkg_resources.require('bob.db.fargo')[0].version
import numpy
import bob.io.base
import bob.io.image
import bob.bio.face
import bob.db.fargo
import bob.ip.facedetect
import bob.ip.draw
import gridtk
from shutil import copyfile
def main(user_input=None):
"""
Main function to detect faces in FARGO frontal images
"""
# Parse the command-line arguments
if user_input is not None:
arguments = user_input
else:
arguments = sys.argv[1:]
prog = os.path.basename(sys.argv[0])
completions = dict(prog=prog, version=version,)
args = docopt(__doc__ % completions,argv=arguments,version='Face detector (%s)' % version,)
# if the user wants more verbosity, lowers the logging level
if args['--verbose'] == 1: logging.getLogger("face_detect_log").setLevel(logging.INFO)
elif args['--verbose'] >= 2: logging.getLogger("face_detect_log").setLevel(logging.DEBUG)
# log file to record errors ...
logfile = open(args['--log'], 'a')
# check user input
if not (args['--protocol'] == 'MC' or args['--protocol'] == 'UD' or args['--protocol'] == 'UO'):
logger.warning("Please provide a valid protocol name, {0} is not !".format(args['--protocol']))
sys.exit()
if not (args['--mod'] == 'RGB' or args['--mod'] == 'NIR'):
logger.warning("Please provide a valid modality, {0} is not !".format(args['--mod']))
sys.exit()
if not (args['--facedetect'] == 'bob' or args['--facedetect'] == 'dlib' or args['--facedetect'] == 'mtcnn'):
logger.warning("Please provide a valid facedetector, {0} is not !".format(args['--mod']))
sys.exit()
if args['--facedetect'] == 'bob':
import bob.ip.facedetect
if args['--facedetect'] == 'dlib':
import bob.ip.dlib
if args['--facedetect'] == 'mtcnn':
import bob.ip.mtcnn
# get the modality and the channel
if args['--mod'] == 'RGB':
modality = 'RGB'
channel = 'color'
if args['--mod'] == 'NIR':
modality = 'NIR'
channel = 'ir'
db = bob.db.fargo.Database()
protocol = 'public_' + args['--protocol'] + '_' + args['--mod']
objs = db.objects(protocol=protocol, groups=['world', 'dev', 'eval'])
# if we are on a grid environment, just find what I have to process.
pos = 0
if sys.version_info[0] < 3:
if os.environ.has_key('SGE_TASK_ID'):
pos = int(os.environ['SGE_TASK_ID']) - 1
if pos >= len(objs):
raise RuntimeError ("Grid request for job {} on a setup with {} jobs".format(pos, len(objs)))
objs = [objs[pos]]
else:
if 'SGE_TASK_ID' in os.environ:
pos = int(os.environ['SGE_TASK_ID']) - 1
if pos >= len(objs):
raise RuntimeError ("Grid request for job {} on a setup with {} jobs".format(pos, len(objs)))
objs = [objs[pos]]
if args['--gridcount']:
print(len(objs))
sys.exit()
# counters
image_counter = 0
no_face_detected = 0
for image in objs:
filename = os.path.join(args['--imagesdir'], image.path)
filename += '.png'
pos_filename = os.path.join(args['--posdir'], image.path)
pos_filename += '.pos'
# if the modality is NIR, also write pos file for depth (they're the same)
if modality == 'NIR':
pos_filename_depth = pos_filename.replace('ir', 'depth')
if os.path.isfile(pos_filename):
logger.warn("pos file for {0} already exists".format(image.path))
if not os.path.isfile(pos_filename_depth) and modality == 'NIR':
logger.warn("copying pos file {} for depth".format(image.path))
if not os.path.isdir(os.path.dirname(pos_filename_depth)):
os.makedirs(os.path.dirname(pos_filename_depth))
copyfile(pos_filename, pos_filename_depth)
continue
logger.info("Detecting face in {0}".format(image.path))
face_image = bob.io.base.load(filename)
# bob.ip.facedetect
if args['--facedetect'] == 'bob':
bounding_box, quality = bob.ip.facedetect.detect_single_face(face_image)
if bounding_box is None:
logger.warn("No face detected in {0}".format(image.path))
logfile.write("No face detected in {0}".format(image.path))
no_face_detected += 1
continue
eyes = bob.ip.facedetect.expected_eye_positions(bounding_box, padding = None)
reyex = int(eyes['reye'][1])
reyey = int(eyes['reye'][0])
leyex = int(eyes['leye'][1])
leyey = int(eyes['leye'][0])
# bob.ip.dlib
if args['--facedetect'] == 'dlib':
landmarks = bob.ip.dlib.DlibLandmarkExtraction(bob_landmark_format=True)(face_image)
if landmarks is None:
leyex = leyey = reyex = reyey = 0
else:
# warning: left and right eyes are swapped according to dlib
leyex = int(landmarks['reye'][1])
leyey = int(landmarks['reye'][0])
reyex = int(landmarks['leye'][1])
reyey = int(landmarks['leye'][0])
# bob.ip.mtcnn
if args['--facedetect'] == 'mtcnn':
bounding_box, landmarks = bob.ip.mtcnn.FaceDetector().detect_single_face(face_image)
if landmarks is None:
leyex = leyey = reyex = reyey = 0
else:
reyex = int(landmarks['reye'][1])
reyey = int(landmarks['reye'][0])
leyex = int(landmarks['leye'][1])
leyey = int(landmarks['leye'][0])
if reyex == 0 or reyey == 0 or leyex == 0 or leyey == 0:
logger.warn("No face detected in {0}".format(image.path))
logfile.write("No face detected in {0}".format(image.path))
no_face_detected += 1
# write dummy bbox, otherwise bob.bio.face's verify fails ...
# dummy eyes will be centered in the image
reyex = 0.4*face_image.shape[0]
reyey = 0.5*face_image.shape[1]
leyex = 0.6*face_image.shape[0]
reyey = 0.5*face_image.shape[1]
if not os.path.isdir(os.path.dirname(pos_filename)):
os.makedirs(os.path.dirname(pos_filename))
eyes_file = open(pos_filename, 'w')
eyes_file.write('{0} {1} {2} {3}'.format(reyex, reyey, leyex, leyey))
eyes_file.close()
# copy file for depth if we are processing NIR
if modality == 'NIR':
if not os.path.isdir(os.path.dirname(pos_filename_depth)):
os.makedirs(os.path.dirname(pos_filename_depth))
copyfile(pos_filename, pos_filename_depth)
continue
if bool(args['--plot']):
from matplotlib import pyplot
if modality == 'RGB':
#bob.ip.draw.box(face_image, bounding_box.topleft, bounding_box.size, color=(255, 0, 0))
bob.ip.draw.cross(face_image, (reyey, reyex), 10, (0, 255, 0))
bob.ip.draw.cross(face_image, (leyey, leyex), 10, (0, 255, 0))
pyplot.imshow(numpy.rollaxis(numpy.rollaxis(face_image, 2),2))
else:
#bob.ip.draw.box(face_image, bounding_box.topleft, bounding_box.size, color=(255))