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

[doc] changed the test image, reformat the docstrings

parent 6cd0955d
#!/usr/bin/env python
# encoding: utf-8
# Guillaume HEUSCH <guillaume.heusch@idiap.ch>
# Tue 5 Apr 11:20:29 CEST 2016
"""Test Units
"""
import nose.tools
import numpy
import bob.ip.skincolorfilter as scf
skin_filter = scf.SkinColorFilter()
def test_circular_mask():
"""
Test the generation of the circular mask
"""
# limit case: the center of the image is located at (0,0)
# so it's considered as inside (x**2 + y**2) = 0 < 0.4
image = numpy.zeros((3, 1, 1))
skin_filter.generate_circular_mask(image)
assert numpy.all(skin_filter.circular_mask), "a 1x1 image should be True"
# easy case - the "cross" should be true
image = numpy.zeros((3, 3, 3))
skin_filter.generate_circular_mask(image)
assert skin_filter.circular_mask[0, 1], "middle-top should be inside"
assert numpy.all(skin_filter.circular_mask[1, :]), "the whole middle line should be inside"
assert skin_filter.circular_mask[2, 1], "middle-bottom should be inside"
# more realistic case - radius will be 0.4*15=6 pixels
image = numpy.zeros((3, 15, 15))
skin_filter.generate_circular_mask(image)
print skin_filter.circular_mask
# left
assert not(skin_filter.circular_mask[7, 1]), "(7,1) should not be inside"
assert skin_filter.circular_mask[7, 2], "(7,2) should be inside"
# top
assert not(skin_filter.circular_mask[1, 7]), "(1,7) should not be inside"
assert skin_filter.circular_mask[2, 7], "(2,7) should be inside"
# right
assert not(skin_filter.circular_mask[7, 13]), "(7,13) should not be inside"
assert skin_filter.circular_mask[7, 12], "(7,12) should be inside"
# bottom
assert not(skin_filter.circular_mask[13, 7]), "(13, 7) should not be inside"
assert skin_filter.circular_mask[12, 7], "(12, 7) should be inside"
def test_luma_mask():
"""
Test the generation of the luma mask
"""
# generate a greyish image
image = numpy.ones((3, 11, 11))*(numpy.random.standard_normal((3,11,11)) + 128)
image[:, 0, :] = 0 # first line is black
image[:, -1, :] = 255 # last line is white
# the circular mask (to compute mean and std luma)
skin_filter.generate_circular_mask(image)
skin_filter.remove_luma(image)
# the first and last line should be all False - extreme values
assert not(numpy.all(skin_filter.luma_mask[:, 0]))
assert not(numpy.all(skin_filter.luma_mask[:, -1]))
# there should be at least one True everywhere else
assert numpy.any(skin_filter.luma_mask)
def test_estimate_parameters():
"""
Test the ML estimation of the Gaussian parameters
"""
# a red image
image = numpy.zeros((3, 11, 11))
image[0, :, :] = 255
skin_filter.get_gaussian_parameters(image)
assert (skin_filter.mean == [1.0, 0.0]).all(), "mean for a red image is not OK"
assert (skin_filter.covariance == [[0.0, 0.0], [0.0, 0.0]]).all(), "covariance for red image is not OK"
# a green image
image = numpy.zeros((3, 11, 11))
image[1, :, :] = 255
skin_filter.get_gaussian_parameters(image)
assert (skin_filter.mean == [0.0, 1.0]).all(), "mean for a green image is not OK"
assert (skin_filter.covariance == [[0.0, 0.0], [0.0, 0.0]]).all(), "covariance for green image is not OK"
...@@ -245,7 +245,8 @@ autodoc_default_flags = ['members', 'undoc-members', 'inherited-members', 'show- ...@@ -245,7 +245,8 @@ autodoc_default_flags = ['members', 'undoc-members', 'inherited-members', 'show-
# For inter-documentation mapping: # For inter-documentation mapping:
from bob.extension.utils import link_documentation from bob.extension.utils import link_documentation
intersphinx_mapping = link_documentation(['python', 'numpy', 'scipy', 'matplotlib', 'bob.db.verification.utils']) #intersphinx_mapping = link_documentation(['python', 'numpy', 'scipy', 'matplotlib', 'bob.db.verification.utils'])
intersphinx_mapping = link_documentation(['bob.ip.facedetect'])
def setup(app): def setup(app):
......
...@@ -7,18 +7,23 @@ ...@@ -7,18 +7,23 @@
import bob.io.base.test_utils import bob.io.base.test_utils
import bob.io.image import bob.io.image
import bob.ip.facedetect import bob.ip.facedetect
from bob.ip.skincolorfilter.skin_color_filter import SkinColorFilter import bob.ip.skincolorfilter
import pkg_resources import pkg_resources
face_image = bob.io.base.load(bob.io.base.test_utils.datafile('001.png', 'bob.ip.skincolorfilter')) face_image = bob.io.base.load(bob.io.base.test_utils.datafile('test-face.jpg', 'bob.ip.skincolorfilter'))
============= =============
Users Guide User Guide
============= =============
This skin color filter relies on the result of face detection. The skin color values This skin color filter relies on the result of face detection, hence you might want to
are estimated from the center of the detected face area. The probability of a pixel use :py:mod:`bob.ip.facedetect` (and in particular :py:func:`bob.ip.facedetect.detect_single_face`)
to be of skin color is modeled as a bivariate gaussian in the normalized rg colorspace to first detect a face in the image.
The skin color distribution is modeled as a bivariate gaussian in the normalised rg colorspace.
The parameters of the distribution are estimated from a circular region centered on the face,
where extreme luma values have been eliminated (see [taylor-spie-2014]_ for details).
Skin pixels detection in a single image Skin pixels detection in a single image
--------------------------------------- ---------------------------------------
...@@ -29,21 +34,22 @@ Hence, to detect skin pixels inside a face image, you should do the following: ...@@ -29,21 +34,22 @@ Hence, to detect skin pixels inside a face image, you should do the following:
.. doctest:: .. doctest::
>>> face_image = bob.io.base.load('001.png') # doctest: +SKIP >>> face_image = bob.io.base.load('test-face.jpg') # doctest: +SKIP
>>> detection = bob.ip.facedetect.detect_single_face(face_image) >>> detection = bob.ip.facedetect.detect_single_face(face_image)
>>> bounding_box, quality = bob.ip.facedetect.detect_single_face(face_image) >>> bounding_box, quality = bob.ip.facedetect.detect_single_face(face_image)
>>> face = face_image[:, bounding_box.top:bounding_box.bottom, bounding_box.left:bounding_box.right] >>> face = face_image[:, bounding_box.top:bounding_box.bottom, bounding_box.left:bounding_box.right]
>>> skin_filter = SkinColorFilter() >>> skin_filter = bob.ip.skincolorfilter.SkinColorFilter()
>>> skin_filter.get_gaussian_parameters(face) >>> skin_filter.estimate_gaussian_parameters(face)
>>> skin_mask = skin_filter.get_skin_pixels(face_image, 0.5) >>> skin_mask = skin_filter.get_skin_mask(face_image, 0.5)
.. plot:: plot/detect_skin_pixels.py .. plot:: plot/detect_skin_pixels.py
:include-source: False :include-source: False
Picture taken from https://stocksnap.io/photo/W7GS1022QN
Skin pixels detection in videos Skin pixels detection in videos
------------------------------- -------------------------------
To detect skin pixels in video, you don't need to re-init the gaussian parameters at each frame. To detect skin pixels in video, you do not need to re-estimate the gaussian parameters at each frame.
However, you can do it if you really want to by calling the appropriate function (i.e. get_gaussian_parameters). However, you can do it by calling :py:meth:`SkinColorFilter.estimate_gaussian_parameters`.
...@@ -5,25 +5,27 @@ import bob.io.base ...@@ -5,25 +5,27 @@ import bob.io.base
import bob.io.base.test_utils import bob.io.base.test_utils
import bob.io.image import bob.io.image
import bob.ip.facedetect import bob.ip.facedetect
from bob.ip.skincolorfilter.skin_color_filter import SkinColorFilter from bob.ip.skincolorfilter import SkinColorFilter
face_image = bob.io.base.load(bob.io.base.test_utils.datafile('001.png', 'bob.ip.skincolorfilter')) face_image = bob.io.base.load(bob.io.base.test_utils.datafile('test-face.jpg', 'bob.ip.skincolorfilter'))
detection = bob.ip.facedetect.detect_single_face(face_image) detection = bob.ip.facedetect.detect_single_face(face_image)
bounding_box, quality = bob.ip.facedetect.detect_single_face(face_image) bounding_box, quality = bob.ip.facedetect.detect_single_face(face_image)
face = face_image[:, bounding_box.top:bounding_box.bottom, bounding_box.left:bounding_box.right] face = face_image[:, bounding_box.top:bounding_box.bottom, bounding_box.left:bounding_box.right]
skin_filter = SkinColorFilter() skin_filter = SkinColorFilter()
skin_filter.get_gaussian_parameters(face) skin_filter.estimate_gaussian_parameters(face)
skin_mask = skin_filter.get_skin_pixels(face_image, 0.5) skin_mask = skin_filter.get_skin_mask(face_image, 0.5)
skin_image = numpy.copy(face_image) skin_image = numpy.copy(face_image)
skin_image[:, numpy.logical_not(skin_mask)] = 0 skin_image[:, numpy.logical_not(skin_mask)] = 0
from matplotlib import pyplot from matplotlib import pyplot
f, ax = pyplot.subplots(2, 1) f, ax = pyplot.subplots(1, 1)
ax[0].set_title('Original Image') ax.set_title('Original Image')
ax[0].set_xticks([]) ax.set_xticks([])
ax[0].set_yticks([]) ax.set_yticks([])
ax[0].imshow(numpy.rollaxis(numpy.rollaxis(face_image, 2),2)) ax.imshow(numpy.rollaxis(numpy.rollaxis(face_image, 2),2))
ax[1].set_title('Detected skin pixels') f, ax = pyplot.subplots(1, 1)
ax[1].set_xticks([]) ax.set_title('Detected skin pixels')
ax[1].set_yticks([]) ax.set_xticks([])
ax[1].imshow(numpy.rollaxis(numpy.rollaxis(skin_image, 2),2)) ax.set_yticks([])
ax.imshow(numpy.rollaxis(numpy.rollaxis(skin_image, 2),2))
...@@ -2,5 +2,5 @@ ...@@ -2,5 +2,5 @@
Python API Python API
============ ============
.. automodule:: bob.ip.skincolorfilter.skin_color_filter .. automodule:: bob.ip.skincolorfilter
:members: :members:
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment