Source code for detectree.image_descriptor
"""Compute image descriptors."""
import cv2
import numpy as np
from PIL import Image
from skimage import color
from skimage.util import shape
from sklearn import preprocessing
from . import utils
__all__ = [
"compute_image_descriptor",
"compute_image_descriptor_from_filepath",
]
[docs]
def compute_image_descriptor(img_rgb, kernels, response_bins_per_axis, num_color_bins):
"""
Compute a GIST descriptor for an RGB image array.
See the `background <https://bit.ly/2KlCICO>`_ example notebook for more details.
Parameters
----------
img_rgb : array-like
The image in RGB format, i.e., in a 3-D array.
kernels : list-like
List of kernel 2-D arrays that correspond to the filter bank.
response_bins_per_axis : int
Number of spatial bins per axis into which the responses to the filter bank will
be aggreated. For example, a value of 2 will aggregate the responses into the
four quadrants of the image (i.e., 2x2, 2 bins in each axis of the image).
num_color_bins : int
Number of color bins per axis of the L*a*b color space with which the joint
color histogram will be computed.
Returns
-------
img_descr : array-like
Vector representing GIST descriptor of `img_rgb`.
"""
# gist descriptor
num_blocks = response_bins_per_axis**2
gist_descr = np.zeros(len(kernels) * num_blocks)
img_gray = color.rgb2gray(img_rgb)
block_shape = tuple(size // response_bins_per_axis for size in img_gray.shape)
divides_evenly = True
for size in img_gray.shape:
if size % response_bins_per_axis != 0:
divides_evenly = False
break
if not divides_evenly:
# TODO: warn?
target_height, target_width = (
size * response_bins_per_axis for size in block_shape
)
img_gray = np.array(
Image.fromarray(img_gray).resize((target_width, target_height))
)
for i, kernel in enumerate(kernels):
filter_response = cv2.filter2D(img_gray, ddepth=-1, kernel=kernel)
response_bins = shape.view_as_blocks(filter_response, block_shape)
bin_sum = response_bins.sum(axis=(2, 3)).flatten()
gist_descr[i * num_blocks : (i + 1) * num_blocks] = bin_sum
# color descriptor
img_lab = color.rgb2lab(img_rgb)
img_lab_dn = img_lab.reshape(img_lab.shape[0] * img_lab.shape[1], img_lab.shape[2])
H, _ = np.histogramdd(img_lab_dn, bins=num_color_bins)
color_descr = H.flatten()
# normalize the gist and color descriptors to the l1 norm and concatenate them
img_descr = np.concatenate(
[
preprocessing.normalize(row.reshape(1, -1), norm="l1").flatten()
for row in [gist_descr, color_descr]
]
)
return img_descr
[docs]
def compute_image_descriptor_from_filepath(
img_filepath, kernels, response_bins_per_axis, num_color_bins
):
"""
Compute a GIST descriptor for RGB image file.
See the `background <https://bit.ly/2KlCICO>`_ example notebook for more details.
Parameters
----------
img_filepath : str, file object or pathlib.Path object
Path to a file, URI, file object opened in binary ('rb') mode, or a Path object
representing the image for which a GIST descriptor will be computed. The value
will be passed to `rasterio.open`.
kernels : list-like
List of kernel 2-D arrays that correspond to the filter bank.
response_bins_per_axis : int
Number of spatial bins per axis into which the responses to the filter bank will
be aggreated. For example, a value of 2 will aggregate the responses into the
four quadrants of the image (i.e., 2x2, 2 bins in each axis of the image).
num_color_bins : int
Number of color bins per axis of the L*a*b color space with which the joint
color histogram will be computed.
Returns
-------
img_descr : array-like
Vector representing GIST descriptor of `img_rgb`.
"""
img_rgb = utils.img_rgb_from_filepath(img_filepath)
return compute_image_descriptor(
img_rgb, kernels, response_bins_per_axis, num_color_bins
)