Over the last decades, the amount of data generated is growing
rapidly, predominantly due to digitalization. Most of today’s data is
unstructured, and this share is increasing. Given that unstructured data
is rich, these data could provide rich insights for scientific research
from a variety of fields and practice alike. Especially images (i.e.,
visual stimuli) are recognized as valuable source of information.
At the same time, vision research and research in psychology shows
that even simple changes in low-level image features (like symmetry,
contrast, or complexity) can have a tremendous effect on a variety of
human judgments. As an example, a statement like “Nut bread is healthier
than potato bread” is more likely to be perceived as true when presented
in a color that is easy to read against a white background (high
contrast) instead of being presented in a color that is difficult to
read against a white background (low contrast; cf. [1]). Thus, it
might be useful to estimate and control for differences in such
low-level visual features in any research that includes visual
stimuli.
imagefluency is an simple R package for
such low-level image scores based on processing fluency theory. The
package allows to get scores for several basic aesthetic principles that
facilitate fluent cognitive processing of images: contrast, complexity /
simplicity, self-similarity, symmetry, and typicality.
as control variables in statistical or prediction models
linking image fluency scores to outcomes of interest (e.g., how
should a typical product packaging look like, do simpler images get more
or less attention on a website, …)
(interpretable) image features in simple machine learning models,
e.g. SVM image classifier
Theoretical background
The most prevailing explanation for how low-level image features
affect human judgments is based on processing fluency theory [2]. Processing
fluency describes the ease of processing a stimulus [3], which
happens instantaneously and automatically [4]. Higher processing fluency results in
a gut-level positive affective response [5]. Notably, a rich body of
literature has shown that processing fluency effects have an impact on a
variety of judgmental domains in our everyday life, including how much
we like things, how much we consider statements to be true, how
trustworthy we judge a person, how risky we think something is, or
whether we buy a product or not (for a review, see [6]).
Several stimulus features have been proposed that result in increased
fluency. In particular, visual symmetry, simplicity, (proto-)typicality,
and contrast were identified to facilitate processing [2]. Recent studies
further discuss self-similarity in light of fluency-based aesthetics
[7, 8], a concept which has been
studied for example in images of natural scenes [9].
Self-similarity can be described as self-repeating patterns within a
stimulus. A typical example are the leaves of ferns that feature the
same shape regardless of any magnification or reduction (i.e., scale
invariance). Another prominent example is romanesco broccoli with its
self-similar surface.
Extracting image features for contrast, self-similarity, simplicity,
symmetry, and typicality therefore constitute the core purpose of the
imagefluency package.
Package overview
Main functions
img_contrast() visual contrast of an image
img_complexity() visual complexity of an image
(opposite of simplicity)
img_self_similarity() visual self-similarity of an
image
img_simplicity() visual simplicity of an image
(opposite of complexity)
img_symmetry() vertical and horizontal symmetry of an
image
img_typicality() visual typicality of a list of images
relative to each other
Other helpful functions
img_read() reads bitmap images into R
rgb2gray() converts images from RGB into grayscale
(might speed up computation)
run_imagefluency() launches a (preliminary) Shiny app
for an interactive demo of the main functions (alternatively, visit the
online version at shinyapps.io)
Installation
You can install the current stable version from CRAN.
install.packages('imagefluency')
To download the latest development version from Github use the
install_github function of the remotes
package.
# install remotes if necessaryif (!require('remotes')) install.packages('remotes')# install imagefluency from githubremotes::install_github('stm/imagefluency')
After installation, the imagefluency package is loaded
the usual way by calling library(imagefluency). The
img_read() function can be used to read an image into R.
Just like with reading in a dataset, img_read() expects the
path to the file as input, e.g.,
img_read('C:/Users/myname/Documents/myimage.jpg').
Currently supported file formats are bmp, jpg, png, and tif.
imagefluency allows to get scores for five image
features that facilitate fluent processing of images: contrast,
complexity / simplicity, self-similarity, symmetry, and typicality.
To use the imagefluency package, first load the library.
library(imagefluency)
Contrast
The function img_contrast() returns the contrast of an
image. Most research defines contrast in images as the root-mean-squared
(RMS) contrast which is the standard deviation of the normalized pixel
intensity values [10]: $\sqrt{\frac{1}{M N}\sum_{i=0}^{N-1}\sum_{j=0}^{M -
1}(I_{ij} - \bar{I})^2}$. The RMS of an image as a measure for
visual contrast has been shown to predict human contrast detection
thresholds well [11]. Therefore, the function
calculates contrast by computing the RMS contrast of the input image.
Consequently, a higher value indicates higher contrast. The image is
normalized if necessary (i.e., normalization into range [0, 1]). For
color images, a weighted average between color the channels is computed
(cf. [8]).
Note that in the following, example images that come with the package
are used. Moreover, the images can be displayed using the
grid.raster() function from the grid
package.
# Example image with relatively high contrast: berriesberries <-img_read(system.file('example_images', 'berries.jpg', package ='imagefluency'))# display imagegrid::grid.raster(berries)# get contrastimg_contrast(berries)
# Example image with relatively low contrast: bikebike <-img_read(system.file('example_images', 'bike.jpg', package ='imagefluency'))# display imagegrid::grid.raster(bike)# get contrastimg_contrast(bike)
Calculating the contrast scores for the two images gives the
following result:
Complexity / Simplicity
The function img_complexity() returns the visual
complexity of an image. Algorithmic information theory indicates that
picture complexity can be measured accurately by image compression rates
because complex images are denser and have fewer redundancies [12, 13]. Therefore, the function
calculates the visual complexity of an image as the ratio between the
compressed and uncompressed image file size. Thus, the value does not
depend on image size.
The function takes the file path of an image file (or URL) or a
pre-loaded image as input argument and returns the ratio of the
compressed divided by the uncompressed image file size. The complexity
values are naturally interpretable and can range between almost 0
(virtually completely compressed image, thus extremely simple image) and
1 (no compression possible, thus extremely complex image). The function
offers to use different image compression algorithms like
jpg, gif, or png with
algorithm = 'zip' as default (for a discussion about the
different algorithms, see [8]).
As most compression algorithms do not depict horizontal and vertical
redundancies equally, the function includes an optional
rotate parameter (default: FALSE). Setting
this parameter to TRUE additionally creates a compressed
version of the rotated image. The overall compressed image’s
file size is computed as the minimum of the original image’s file size
and the file size of the rotated image.
The function img_simplicity() returns the visual
simplicity of an image. Image simplicity is the complement to image
complexity and therefore calculated as 1 minus the complexity score
(i.e., the compression rate). Values can range between 0 (no compression
possible, thus extremely complex image) and almost 1 (virtually
completely compressed image, thus extremely simple image).
# Example image with high complexity: treestrees <-img_read(system.file('example_images', 'trees.jpg', package ='imagefluency'))# display imagegrid::grid.raster(trees)# get complexityimg_complexity(trees)
# Example image with low complexity: skysky <-img_read(system.file('example_images', 'sky.jpg', package ='imagefluency'))# display imagegrid::grid.raster(sky)# get complexityimg_complexity(sky)
Calculating the complexity scores for the two images gives the
following result:
Self-similarity
The function img_self_similarity() returns the
self-similarity of an image. Self-similarity can be measured with the
Fourier power spectrum of an image. Previous research has identified
that the spectral power of natural scenes falls with spatial frequencies
(f) according to a power law
($\frac{1}{f^p}$) with values of p near the value 2, which indicates
scale invariance (for a review, see [14]). Therefore, the function
computes self-similarity via the slope of the log-log power spectrum of
the image using OLS.
The value for self-similarity that is returned by the function is
calculated as self-similarity = |slope + 2| * (−1). That
is, the measure reaches its maximum value of 0 for a slope of −2, and any deviation from −2 results in negative values that are more
negative the higher the deviation from −2. Thus, the range of the self-similarity
scores is −∞ to 0. For color images, the weighted average
between each color channel’s values is computed.
It is possible to get the raw regression slope (instead of the
transformed value which indicates self-similarity) by using the option
raw = TRUE. More options include the possibility to plot
the log-log power spectrum (logplot = TRUE) and to base the
computation of the slope on the full frequency spectrum
(full = TRUE). See the function’s help file for details
(i.e., ?img_self_similarity).
# Example image with high self-similarity: romanescoromanesco <-img_read(system.file('example_images', 'romanesco.jpg', package ='imagefluency'))# display imagegrid::grid.raster(romanesco)# get self-similarityimg_self_similarity(romanesco)
# Example image with low self-similarity: officeoffice <-img_read(system.file('example_images', 'office.jpg', package ='imagefluency'))# display imagegrid::grid.raster(office)# get self-similarityimg_self_similarity(office)
Calculating the self-similarity scores for the two images gives the
result below. The score for the romanesco broccoli is much closer to the
maximum possible value of 0, hence much more self-similar.
Symmetry
The function img_symmetry() returns the vertical and
horizontal symmetry of an image as a numeric value between 0 (not
symmetrical) and 1 (perfectly symmetrical).
Symmetry is computed as the correlation of corresponding image halves
(i.e., the pairwise correlation of the corresponding pixels, cf. [15]). As the
perceptual mirror axis is not necessarily exactly in the middle of a
picture, the function detects in a first step the ‘optimal’ mirror axis
by estimating several symmetry values with different positions for the
mirror axis. To this end, the mirror axis is automatically shifted up to
5% and to the right (in the case of vertical symmetry; analogously for
horizontal symmetry). In the second step, the overall symmetry score is
computed as the maximum of the symmetry scores given the different
mirror axes. For color images, the weighted average between each color
channel’s values is computed. See [8] for details.
The function further has two optional logical parameters:
vertical and horizontal (both
TRUE by default). If one of the parameter is set to
FALSE, the vertical or horizontal symmetry is not computed,
respectively. See the function’s help file (i.e.,
?img_symmetry) for information about the additional options
shift_range and per_channel.
# Example image with high vertical symmetry: railsrails <-img_read(system.file('example_images', 'rails.jpg', package ='imagefluency'))# display imagegrid::grid.raster(rails)# get only vertical symmetryimg_symmetry(rails, horizontal =FALSE)
# Example image with low vertical symmetry: bridgebridge <-img_read(system.file('example_images', 'bridge.jpg', package ='imagefluency'))# display imagegrid::grid.raster(bridge)# get only vertical symmetryimg_symmetry(bridge, horizontal =FALSE)
Calculating the vertical symmetry scores for the two images gives the
following result:
Image typicality
The function img_typicality() returns the visual
typicality of a set of images relative to each other. Values
can range between -1 (inversely typical) over 0 (not typical) to 1
(perfectly typical). That is, higher absolute values indicate a larger
typicality.
The typicality score is computed as the correlation of a particular
image with the average representation of all images, i.e., the mean of
all images [16]. That is, the typicality of an
image can not be assessed in isolation, but only in comparison to set of
images from the same category.
For color images, the weighted average between each color channel’s
values is computed. If the images have different dimensions they are
automatically resized to the smallest height and width. Rescaling of the
images prior to computing the typicality scores can be specified with
the optional rescaling parameter (must be a numeric value). With
rescaling it is possible to assess typicality at different perceptual
levels (see [17] for details). Most users won’t
need any rescaling and can use the default
(rescale = NULL).
The following example shows three images of which two depict valleys
in the mountains and one depicts fireworks. Therefore, the fireworks
image is in comparison rather low in typicality in this set of images
(i.e., atypical). It is important to note that an image’s typicality
score highly depends on the reference set to which the image is compared
to.
# Example images depicting valleys: valley_white, valley_green# Example image depicting fireworks: fireworksvalley_white <-img_read(system.file('example_images', 'valley_white.jpg', package ='imagefluency'))valley_green <-img_read(system.file('example_images', 'valley_green.jpg', package ='imagefluency'))fireworks <-img_read(system.file('example_images', 'fireworks.jpg', package ='imagefluency'))# create image set as listimglist <-list(valley_white, fireworks, valley_green)# get typicalityimg_typicality(imglist)
Calculating the typicality scores for the three images gives the
following result:
Summary
imagefluency is an simple R package for
image fluency scores. The package allows to get scores for several basic
aesthetic principles that facilitate fluent cognitive processing of
images. It straightforward to use and allows for an easy conversion of
unstructured data into structured image features. These structured image
features are naturally interpretable (i.e., no black-box-model).
Finally, including such image information in statistical models might
increase a model’s statistical and predictive power.
References
1.
Hansen, J., Dechêne, A., & Wänke, M.
(2008). Discrepant fluency increases subjective truth. Journal of
Experimental Social Psychology, 44(3), 687–691. https://doi.org/10.1016/j.jesp.2007.04.005
2.
Reber, R., Schwarz, N., & Winkielman, P.
(2004). Processing fluency and aesthetic pleasure: Is beauty in the
perceiver’s processing experience? Personality and Social Psychology
Review, 8(4), 364–382. https://doi.org/10.1207/s15327957pspr0804_3
3.
Schwarz, N. (2004). Metacognitive experiences
in consumer judgment and decision making. Journal of Consumer
Psychology, 14(4), 332–348. https://doi.org/10.1207/s15327663jcp1404_2
4.
Graf, L. K. M., & Landwehr, J. R. (2015). A
dual-process perspective on fluency-based aesthetics: The
pleasure-interest model of aesthetic liking. Personality and Social
Psychology Review, 19(4), 395–410. https://doi.org/10.1177/1088868315574978
5.
Winkielman, P., & Cacioppo, J. T. (2001).
Mind at ease puts a smile on the face: Psychophysiological evidence that
processing facilitation elicits positive affect. Journal of
Personality and Social Psychology, 81(6), 989. https://doi.org/10.1037//0022-3514.81.6.989
6.
Alter, A. L., & Oppenheimer, D. M. (2009).
Uniting the tribes of fluency to form a metacognitive nation.
Personality and Social Psychology Review, 13(3),
219–235. https://doi.org/10.1177/1088868309341564
7.
Joye, Y., Steg, L., Ünal, A. B., & Pals, R.
(2016). When complex is easy on the mind: Internal repetition of visual
information in complex objects is a source of perceptual fluency.
Journal of Experimental Psychology: Human Perception and
Performance, 42(1), 103–114. https://doi.org/10.1037/xhp0000105
8.
Mayer, S., & Landwehr, J. R. (2018).
Quantifying visual aesthetics based on processing fluency theory: Four
algorithmic measures for antecedents of aesthetic preferences.
Psychology of Aesthetics, Creativity, and the Arts,
12(4), 399–431. https://doi.org/10.1037/aca0000187
Landwehr, J. R., Labroo, A. A., & Herrmann,
A. (2011). Gut liking for the ordinary: Incorporating design fluency
improves automobile sales forecasts. Marketing Science,
30(3), 416–429. https://doi.org/10.1287/mksc.1110.0633
14.
Simoncelli, E. P., & Olshausen, B. A.
(2001). Natural image statistics and neural representation. Annual
Review of Neuroscience, 24(1), 1193–1216. https://doi.org/10.1146/annurev.neuro.24.1.1193
15.
Mayer, S., & Landwehr, J. R. (2014). When
complexity is symmetric: The interplay of two core determinants of
visual aesthetics. In J. Cotte & S. Wood (Eds.), Advances in Consumer Research (Vol. 42, pp.
608–609). Duluth, MN: Association for Consumer Research.
16.
Perrett, D. I., May, K. A., & Yoshikawa, S.
(1994). Facial shape and judgements of female attractiveness.
Nature, 368(6468), 239–242. https://doi.org/10.1038/368239a0