Source code for pliers.extractors.image
'''
Extractors that operate primarily or exclusively on Image stimuli.
'''
from functools import partial
import numpy as np
import pandas as pd
from pliers.stimuli.image import ImageStim
from pliers.extractors.base import Extractor, ExtractorResult
from pliers.utils import attempt_to_import, verify_dependencies, listify
from pliers.support.due import due, Url, Doi
cv2 = attempt_to_import('cv2')
face_recognition = attempt_to_import('face_recognition')
class ImageExtractor(Extractor):
''' Base Image Extractor class; all subclasses can only be applied to
images. '''
_input_type = ImageStim
[docs]class BrightnessExtractor(ImageExtractor):
''' Gets the average luminosity of the pixels in the image '''
VERSION = '1.0'
def _extract(self, stim):
data = stim.data
brightness = np.amax(data, 2).mean() / 255.0
return ExtractorResult(np.array([[brightness]]), stim, self,
features=['brightness'])
[docs]class SharpnessExtractor(ImageExtractor):
''' Gets the degree of blur/sharpness of the image '''
VERSION = '1.0'
def _extract(self, stim):
verify_dependencies(['cv2'])
# Taken from
# http://stackoverflow.com/questions/7765810/is-there-a-way-to-detect-if-an-image-is-blurry?lq=1
data = stim.data
gray_image = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
sharpness = np.max(
cv2.convertScaleAbs(cv2.Laplacian(gray_image, 3))) / 255.0
return ExtractorResult(np.array([[sharpness]]), stim, self,
features=['sharpness'])
[docs]class VibranceExtractor(ImageExtractor):
''' Gets the variance of color channels of the image '''
VERSION = '1.0'
def _extract(self, stim):
data = stim.data
vibrance = np.var(data, 2).mean()
return ExtractorResult(np.array([[vibrance]]), stim, self,
features=['vibrance'])
[docs]class SaliencyExtractor(ImageExtractor):
''' Determines the saliency of the image using Itti & Koch (1998) algorithm
implemented in pySaliencyMap '''
@due.dcite(Doi("10.1109/34.730558"),
description="Image saliency estimation",
path='pliers.extractors.image.SilencyExtractor',
tags=["implementation"])
def _extract(self, stim):
from pliers.external.pysaliency import pySaliencyMap
# pySaliencyMap from https://github.com/akisato-/pySaliencyMap
# Initialize variables
h, w, c = stim.data.shape
sm = pySaliencyMap.pySaliencyMap(h, w)
# Compute saliency maps and store full maps as derivatives
stim.derivatives = dict()
stim.derivatives['saliency_map'] = sm.SMGetSM(stim.data)
stim.derivatives['binarized_map'] = sm.SMGetBinarizedSM(
stim.data) # thresholding done using Otsu
# Compute summary statistics
output = {}
output['max_saliency'] = np.max(stim.derivatives['saliency_map'])
output['max_y'], output['max_x'] = [list(i)[0] for i in np.where(
stim.derivatives['saliency_map'] == output['max_saliency'])]
output['frac_high_saliency'] = np.sum(
stim.derivatives['binarized_map']/255.0)/(h * w)
return ExtractorResult(np.array([list(output.values())]), stim, self,
features=list(output.keys()))
class FaceRecognitionFeatureExtractor(ImageExtractor):
_log_attributes = ('face_recognition_kwargs',)
def __init__(self, **face_recognition_kwargs):
verify_dependencies(['face_recognition'])
self.face_recognition_kwargs = face_recognition_kwargs
func = getattr(face_recognition.api, self._feature)
self.func = partial(func, **face_recognition_kwargs)
super().__init__()
def get_feature_names(self):
return self._feature
def _extract(self, stim):
values = self.func(stim.data)
feature_names = listify(self.get_feature_names())
return ExtractorResult(values, stim, self, features=feature_names)
def _to_df(self, result):
cols = listify(self._feature)
return pd.DataFrame([[r] for r in result._data], columns=cols)
[docs]class FaceRecognitionFaceEncodingsExtractor(FaceRecognitionFeatureExtractor):
''' Uses the face_recognition package to extract a 128-dimensional encoding
for every face detected in an image. For details, see documentation for
face_recognition.api.face_encodings. '''
_feature = 'face_encodings'
[docs]class FaceRecognitionFaceLandmarksExtractor(FaceRecognitionFeatureExtractor):
''' Uses the face_recognition package to extract the locations of named
features of faces in the image. For details, see documentation for
face_recognition.api.face_landmarks.'''
_feature = 'face_landmarks'
def _to_df(self, result):
data = pd.DataFrame.from_records(result._data)
data.columns = ['{}_{}'.format(self._feature, c) for c in data.columns]
return data
[docs]class FaceRecognitionFaceLocationsExtractor(FaceRecognitionFeatureExtractor):
''' Uses the face_recognition package to extract bounding boxes for all
faces in an image. For details, see documentation for
face_recognition.api.face_locations. '''
_feature = 'face_locations'