Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
parent
00ad49a143
commit
45fb349a7d
5098 changed files with 952558 additions and 85 deletions
321
venv/Lib/site-packages/skimage/feature/haar.py
Normal file
321
venv/Lib/site-packages/skimage/feature/haar.py
Normal file
|
@ -0,0 +1,321 @@
|
|||
|
||||
from itertools import chain
|
||||
from operator import add
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ._haar import haar_like_feature_coord_wrapper
|
||||
from ._haar import haar_like_feature_wrapper
|
||||
from ..color import gray2rgb
|
||||
from ..draw import rectangle
|
||||
from .._shared.utils import check_random_state
|
||||
from ..util import img_as_float
|
||||
|
||||
FEATURE_TYPE = ('type-2-x', 'type-2-y',
|
||||
'type-3-x', 'type-3-y',
|
||||
'type-4')
|
||||
|
||||
|
||||
def _validate_feature_type(feature_type):
|
||||
"""Transform feature type to an iterable and check that it exists."""
|
||||
if feature_type is None:
|
||||
feature_type_ = FEATURE_TYPE
|
||||
else:
|
||||
if isinstance(feature_type, str):
|
||||
feature_type_ = [feature_type]
|
||||
else:
|
||||
feature_type_ = feature_type
|
||||
for feat_t in feature_type_:
|
||||
if feat_t not in FEATURE_TYPE:
|
||||
raise ValueError(
|
||||
'The given feature type is unknown. Got {} instead of one'
|
||||
' of {}.'.format(feat_t, FEATURE_TYPE))
|
||||
return feature_type_
|
||||
|
||||
|
||||
def haar_like_feature_coord(width, height, feature_type=None):
|
||||
"""Compute the coordinates of Haar-like features.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
width : int
|
||||
Width of the detection window.
|
||||
height : int
|
||||
Height of the detection window.
|
||||
feature_type : str or list of str or None, optional
|
||||
The type of feature to consider:
|
||||
|
||||
- 'type-2-x': 2 rectangles varying along the x axis;
|
||||
- 'type-2-y': 2 rectangles varying along the y axis;
|
||||
- 'type-3-x': 3 rectangles varying along the x axis;
|
||||
- 'type-3-y': 3 rectangles varying along the y axis;
|
||||
- 'type-4': 4 rectangles varying along x and y axis.
|
||||
|
||||
By default all features are extracted.
|
||||
|
||||
Returns
|
||||
-------
|
||||
feature_coord : (n_features, n_rectangles, 2, 2), ndarray of list of \
|
||||
tuple coord
|
||||
Coordinates of the rectangles for each feature.
|
||||
feature_type : (n_features,), ndarray of str
|
||||
The corresponding type for each feature.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> from skimage.transform import integral_image
|
||||
>>> from skimage.feature import haar_like_feature_coord
|
||||
>>> feat_coord, feat_type = haar_like_feature_coord(2, 2, 'type-4')
|
||||
>>> feat_coord # doctest: +SKIP
|
||||
array([ list([[(0, 0), (0, 0)], [(0, 1), (0, 1)],
|
||||
[(1, 1), (1, 1)], [(1, 0), (1, 0)]])], dtype=object)
|
||||
>>> feat_type
|
||||
array(['type-4'], dtype=object)
|
||||
|
||||
"""
|
||||
feature_type_ = _validate_feature_type(feature_type)
|
||||
|
||||
feat_coord, feat_type = zip(*[haar_like_feature_coord_wrapper(width,
|
||||
height,
|
||||
feat_t)
|
||||
for feat_t in feature_type_])
|
||||
|
||||
return np.concatenate(feat_coord), np.hstack(feat_type)
|
||||
|
||||
|
||||
def haar_like_feature(int_image, r, c, width, height, feature_type=None,
|
||||
feature_coord=None):
|
||||
"""Compute the Haar-like features for a region of interest (ROI) of an
|
||||
integral image.
|
||||
|
||||
Haar-like features have been successfully used for image classification and
|
||||
object detection [1]_. It has been used for real-time face detection
|
||||
algorithm proposed in [2]_.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
int_image : (M, N) ndarray
|
||||
Integral image for which the features need to be computed.
|
||||
r : int
|
||||
Row-coordinate of top left corner of the detection window.
|
||||
c : int
|
||||
Column-coordinate of top left corner of the detection window.
|
||||
width : int
|
||||
Width of the detection window.
|
||||
height : int
|
||||
Height of the detection window.
|
||||
feature_type : str or list of str or None, optional
|
||||
The type of feature to consider:
|
||||
|
||||
- 'type-2-x': 2 rectangles varying along the x axis;
|
||||
- 'type-2-y': 2 rectangles varying along the y axis;
|
||||
- 'type-3-x': 3 rectangles varying along the x axis;
|
||||
- 'type-3-y': 3 rectangles varying along the y axis;
|
||||
- 'type-4': 4 rectangles varying along x and y axis.
|
||||
|
||||
By default all features are extracted.
|
||||
|
||||
If using with `feature_coord`, it should correspond to the feature
|
||||
type of each associated coordinate feature.
|
||||
feature_coord : ndarray of list of tuples or None, optional
|
||||
The array of coordinates to be extracted. This is useful when you want
|
||||
to recompute only a subset of features. In this case `feature_type`
|
||||
needs to be an array containing the type of each feature, as returned
|
||||
by :func:`haar_like_feature_coord`. By default, all coordinates are
|
||||
computed.
|
||||
|
||||
Returns
|
||||
-------
|
||||
haar_features : (n_features,) ndarray of int or float
|
||||
Resulting Haar-like features. Each value is equal to the subtraction of
|
||||
sums of the positive and negative rectangles. The data type depends of
|
||||
the data type of `int_image`: `int` when the data type of `int_image`
|
||||
is `uint` or `int` and `float` when the data type of `int_image` is
|
||||
`float`.
|
||||
|
||||
Notes
|
||||
-----
|
||||
When extracting those features in parallel, be aware that the choice of the
|
||||
backend (i.e. multiprocessing vs threading) will have an impact on the
|
||||
performance. The rule of thumb is as follows: use multiprocessing when
|
||||
extracting features for all possible ROI in an image; use threading when
|
||||
extracting the feature at specific location for a limited number of ROIs.
|
||||
Refer to the example
|
||||
:ref:`sphx_glr_auto_examples_applications_plot_haar_extraction_selection_classification.py`
|
||||
for more insights.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> from skimage.transform import integral_image
|
||||
>>> from skimage.feature import haar_like_feature
|
||||
>>> img = np.ones((5, 5), dtype=np.uint8)
|
||||
>>> img_ii = integral_image(img)
|
||||
>>> feature = haar_like_feature(img_ii, 0, 0, 5, 5, 'type-3-x')
|
||||
>>> feature
|
||||
array([-1, -2, -3, -4, -1, -2, -3, -4, -1, -2, -3, -4, -1, -2, -3, -4, -1,
|
||||
-2, -3, -4, -1, -2, -3, -4, -1, -2, -3, -1, -2, -3, -1, -2, -3, -1,
|
||||
-2, -1, -2, -1, -2, -1, -1, -1])
|
||||
|
||||
You can compute the feature for some pre-computed coordinates.
|
||||
|
||||
>>> from skimage.feature import haar_like_feature_coord
|
||||
>>> feature_coord, feature_type = zip(
|
||||
... *[haar_like_feature_coord(5, 5, feat_t)
|
||||
... for feat_t in ('type-2-x', 'type-3-x')])
|
||||
>>> # only select one feature over two
|
||||
>>> feature_coord = np.concatenate([x[::2] for x in feature_coord])
|
||||
>>> feature_type = np.concatenate([x[::2] for x in feature_type])
|
||||
>>> feature = haar_like_feature(img_ii, 0, 0, 5, 5,
|
||||
... feature_type=feature_type,
|
||||
... feature_coord=feature_coord)
|
||||
>>> feature
|
||||
array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, -1, -3, -1, -3, -1, -3, -1, -3, -1,
|
||||
-3, -1, -3, -1, -3, -2, -1, -3, -2, -2, -2, -1])
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] https://en.wikipedia.org/wiki/Haar-like_feature
|
||||
.. [2] Oren, M., Papageorgiou, C., Sinha, P., Osuna, E., & Poggio, T.
|
||||
(1997, June). Pedestrian detection using wavelet templates.
|
||||
In Computer Vision and Pattern Recognition, 1997. Proceedings.,
|
||||
1997 IEEE Computer Society Conference on (pp. 193-199). IEEE.
|
||||
http://tinyurl.com/y6ulxfta
|
||||
:DOI:`10.1109/CVPR.1997.609319`
|
||||
.. [3] Viola, Paul, and Michael J. Jones. "Robust real-time face
|
||||
detection." International journal of computer vision 57.2
|
||||
(2004): 137-154.
|
||||
https://www.merl.com/publications/docs/TR2004-043.pdf
|
||||
:DOI:`10.1109/CVPR.2001.990517`
|
||||
|
||||
"""
|
||||
if feature_coord is None:
|
||||
feature_type_ = _validate_feature_type(feature_type)
|
||||
|
||||
return np.hstack(list(chain.from_iterable(
|
||||
haar_like_feature_wrapper(int_image, r, c, width, height, feat_t,
|
||||
feature_coord)
|
||||
for feat_t in feature_type_)))
|
||||
else:
|
||||
if feature_coord.shape[0] != feature_type.shape[0]:
|
||||
raise ValueError("Inconsistent size between feature coordinates"
|
||||
"and feature types.")
|
||||
|
||||
mask_feature = [feature_type == feat_t for feat_t in FEATURE_TYPE]
|
||||
haar_feature_idx, haar_feature = zip(
|
||||
*[(np.flatnonzero(mask),
|
||||
haar_like_feature_wrapper(int_image, r, c, width, height,
|
||||
feat_t, feature_coord[mask]))
|
||||
for mask, feat_t in zip(mask_feature, FEATURE_TYPE)
|
||||
if np.count_nonzero(mask)])
|
||||
|
||||
haar_feature_idx = np.concatenate(haar_feature_idx)
|
||||
haar_feature = np.concatenate(haar_feature)
|
||||
|
||||
haar_feature[haar_feature_idx] = haar_feature.copy()
|
||||
return haar_feature
|
||||
|
||||
|
||||
def draw_haar_like_feature(image, r, c, width, height,
|
||||
feature_coord,
|
||||
color_positive_block=(1., 0., 0.),
|
||||
color_negative_block=(0., 1., 0.),
|
||||
alpha=0.5, max_n_features=None, random_state=None):
|
||||
"""Visualization of Haar-like features.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : (M, N) ndarray
|
||||
The region of an integral image for which the features need to be
|
||||
computed.
|
||||
r : int
|
||||
Row-coordinate of top left corner of the detection window.
|
||||
c : int
|
||||
Column-coordinate of top left corner of the detection window.
|
||||
width : int
|
||||
Width of the detection window.
|
||||
height : int
|
||||
Height of the detection window.
|
||||
feature_coord : ndarray of list of tuples or None, optional
|
||||
The array of coordinates to be extracted. This is useful when you want
|
||||
to recompute only a subset of features. In this case `feature_type`
|
||||
needs to be an array containing the type of each feature, as returned
|
||||
by :func:`haar_like_feature_coord`. By default, all coordinates are
|
||||
computed.
|
||||
color_positive_rectangle : tuple of 3 floats
|
||||
Floats specifying the color for the positive block. Corresponding
|
||||
values define (R, G, B) values. Default value is red (1, 0, 0).
|
||||
color_negative_block : tuple of 3 floats
|
||||
Floats specifying the color for the negative block Corresponding values
|
||||
define (R, G, B) values. Default value is blue (0, 1, 0).
|
||||
alpha : float
|
||||
Value in the range [0, 1] that specifies opacity of visualization. 1 -
|
||||
fully transparent, 0 - opaque.
|
||||
max_n_features : int, default=None
|
||||
The maximum number of features to be returned.
|
||||
By default, all features are returned.
|
||||
random_state : int, RandomState instance or None, optional
|
||||
If int, random_state is the seed used by the random number generator;
|
||||
If RandomState instance, random_state is the random number generator;
|
||||
If None, the random number generator is the RandomState instance used
|
||||
by `np.random`. The random state is used when generating a set of
|
||||
features smaller than the total number of available features.
|
||||
|
||||
Returns
|
||||
-------
|
||||
features : (M, N), ndarray
|
||||
An image in which the different features will be added.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> from skimage.feature import haar_like_feature_coord
|
||||
>>> from skimage.feature import draw_haar_like_feature
|
||||
>>> feature_coord, _ = haar_like_feature_coord(2, 2, 'type-4')
|
||||
>>> image = draw_haar_like_feature(np.zeros((2, 2)),
|
||||
... 0, 0, 2, 2,
|
||||
... feature_coord,
|
||||
... max_n_features=1)
|
||||
>>> image
|
||||
array([[[0. , 0.5, 0. ],
|
||||
[0.5, 0. , 0. ]],
|
||||
<BLANKLINE>
|
||||
[[0.5, 0. , 0. ],
|
||||
[0. , 0.5, 0. ]]])
|
||||
|
||||
"""
|
||||
random_state = check_random_state(random_state)
|
||||
color_positive_block = np.asarray(color_positive_block, dtype=np.float64)
|
||||
color_negative_block = np.asarray(color_negative_block, dtype=np.float64)
|
||||
|
||||
if max_n_features is None:
|
||||
feature_coord_ = feature_coord
|
||||
else:
|
||||
feature_coord_ = random_state.choice(feature_coord,
|
||||
size=max_n_features,
|
||||
replace=False)
|
||||
|
||||
output = np.copy(image)
|
||||
if len(image.shape) < 3:
|
||||
output = gray2rgb(image)
|
||||
output = img_as_float(output)
|
||||
|
||||
for coord in feature_coord_:
|
||||
for idx_rect, rect in enumerate(coord):
|
||||
coord_start, coord_end = rect
|
||||
coord_start = tuple(map(add, coord_start, [r, c]))
|
||||
coord_end = tuple(map(add, coord_end, [r, c]))
|
||||
rr, cc = rectangle(coord_start, coord_end)
|
||||
|
||||
if ((idx_rect + 1) % 2) == 0:
|
||||
new_value = ((1 - alpha) *
|
||||
output[rr, cc] + alpha * color_positive_block)
|
||||
else:
|
||||
new_value = ((1 - alpha) *
|
||||
output[rr, cc] + alpha * color_negative_block)
|
||||
output[rr, cc] = new_value
|
||||
|
||||
return output
|
Loading…
Add table
Add a link
Reference in a new issue