1 Background

The Munsell system provides a quantitative (numeric) description of color that is approximately linear in terms of average human perception, and, conveniently isolates the independent qualities of color into hue, value, and chroma. Moving from one chip to the next represents a linear traversal through a continuous, 3D (hue, value, chroma) color space. The presentation (soil color book) and notation (e.g. 10YR 3/3) that we are familiar with is based on a discretization of that space into perceptually-compact units (the color chips) that offers sufficient contrast for field identification without an overwhelming number of possibilities. For example, our ability to perceive contrast in lightness (Munsell value) is roughly 2-4x greater than our ability to perceive contrast in chroma: hence the lack of chips representing /5, /7, /9, etc..

Given that the Munsell system is quantitative and roughly linear in terms of human color perception, it is entirely possible to:

  • treat value and chroma as numeric entities
  • interpolate between chips (hue, value, or chroma)
  • simulate mixtures of two or more colors in Munsell notation

I’d recommend SSSA special publication #31, any book on color science, or one of several excellent websites. Our definition of “soil color contrast” is based on the quantitative, linear nature of the Munsell system.

An accurate simulation of pigment mixtures (“subtractive” color mixtures) is incredibly complex due to factors that aren’t easily measured or controlled: pigment solubility, pigment particle size distribution, water content, substrate composition, and physical obstruction to name a few. That said, it is possible to simulate reasonable, subtractive color mixtures given a reference spectra library (350-800nm) and some assumptions about pigment qualities and lighting. For the purposes of estimating a mixture of soil colors (these are pigments after all) we can relax these assumptions and assume a standard light source. The only missing piece is the spectral library for all Munsell chips in our color books.

Thankfully, Scott Burns has outlined the entire process, and Paul Centore has provided a Munsell color chip reflectance spectra library. The estimation of a subtractive mixture of soil colors can proceed as follows:

  1. look-up the associated spectra for each color
  2. compute the weighted (area proportion) geometric mean of spectra
  3. either:
  • search for the closest matching spectra in the reference library, or
  • compute a new reluctance spectra by integration over standard observer and illuminant
  1. convert the final spectra (reference, or computed) to closest Munsell chip

Key assumptions include:

  • similar particle size distribution
  • similar mineralogy (i.e. pigmentation qualities)
  • similar water content
  • similar scattering coefficients

For the purposes of estimating (for example) a “mixed soil color within the top 18cm of soil” these assumptions are usually valid. Again, these are estimates that are ultimately “snapped” to the nearest chip and not do not need to approach the accuracy of paint-matching systems.

So what is a reasonable answer to the following soil color mixture question: 50% 5YR 2/2 + 50% 10YR 4/4 = ?.

1.1 Munsell Spectral Library

library(aqp)
library(lattice)
library(tactile)
library(sharpshootR)

# need this for mixingMethod = 'reference'
library(gower)

# need this for colorMixtureVenn()
library(venn)

# local copy of the Munsell chip spectral library
# c/o http://www.munsellcolourscienceforpainters.com/
# odd chroma spectra via interpolation
# see ?munsell.spectra for details
# try aqp:::.summarizeMunsellSpectraRanges()
data(munsell.spectra)

# all hues, limit to specific hue / chroma slice
x <- munsell.spectra[munsell.spectra$value  == 6 & munsell.spectra$chroma == 8, ]

# each Munsell chip has a 36-element spectra
# ranging from 380-730 nm
# table(x$munsell)

# spectra IDs
x$ID <- factor(x$munsell)
# create a color / chip
cols <- parseMunsell(as.character(levels(x$ID)))

# plot style
tps <- tactile.theme(superpose.line = list(col = cols, lwd = 2))

# final figure
xyplot(
  reflectance ~ wavelength, groups = ID, data = x, 
  par.settings = tps,
  main = 'Value 6 / Chroma 8',
  type = c('l', 'g'),
  ylab = 'Reflectance',
  xlab = 'Wavelength (nm)',
  scales = list(tick.number = 12),
  xlim = c(370, 740)
)

1.2 Implementation

Required packages, be sure to get the latest {aqp} and {sharpshootR} from GitHub.

library(aqp)
library(lattice)
library(latticeExtra)
library(tactile)
library(sharpshootR)
library(gower)
library(venn)
library(cluster)

Create a vector of colors to mix, and evaluate color contrast metrics.

colors <- c('5YR 2/2', '10YR 4/4')
colorContrast(m1 = colors[1], m2 = colors[2])
##        m1       m2 dH dV dC    dE00        cc
## 1 5YR 2/2 10YR 4/4  2  2  2 19.8106 Prominent

We can see that these colors are 2 hue, 2 value, and 2 chroma “chips” apart from each other. This evaluates to a prominent soil color contrast class and \(\Delta{E_{00}}\) of about 20.

A picture is far more intuitive.

par(bg = 'black', fg = 'white', mar = c(0, 0, 0, 0))
colorContrastPlot(m1 = colors[1], m2 = colors[2])

Simulate a mixture via mixMunsell. See the online documentation for details on the method and relevant citations.

# just the closest match
mixed <- mixMunsell(colors, mixingMethod = 'reference')

# top 5 matches, decreasing order
mixed.5 <- mixMunsell(colors, mixingMethod = 'reference', n = 5)

Left to right: original colors-to-mix and final mixture candidate (10YR 3/3). This is the Munsell chip associated with the reference spectra that is closest to the weighted geometric mean of the source spectra.

par(bg = 'black', fg = 'white', mar = c(0, 0, 0, 0))
soilPalette(parseMunsell(c(colors, mixed$munsell)), lab = c(colors, mixed$munsell))

Evaluate the top 5 mixture candidates (ranked by spectral distance) using metrics of color contrast. Note that color contrast does not always correlate with spectral distance.

par(bg = 'black', fg = 'white')
colorContrastPlot(
  m1 = rep(mixed$munsell, times = nrow(mixed.5)),
  m2 = mixed.5$munsell,
  labels = c('closest match', 'top 5 matches')
  )

1.3 Results

Demonstrate reference spectra for the source colors and final mixture. The dashed line is the weighted geometric mean spectra.

plotColorMixture(colors, mixingMethod = 'reference', showMixedSpec = TRUE)

50% 5YR 2/2 + 50% 10YR 4/4 = 10YR 3/3.

What do you think, is the mixture plausible? Experiments with real soil material + Nix Pro sensor measurements, visible-spectrum spectrophotometer pending.

1.3.1 Mollic Epipedon Mixing Rule

Consider the physical mixture of soil material 0 to 18cm, with two horizons spanning 0-12cm, and 12-18cm. Assume that the soil material is of roughly the same soil texture and has similar reflective properties.

60% 10YR 2/2 + 40% 10Y 6/6 = 5Y 3/3

# horizon thickness (cm)
w <- c(12, 8)

# moist soil colors
m <- c('10YR 2/2', '10Y 6/6')

plotColorMixture(m, w, mixingMethod = 'exact', label.cex = 0.65, overlapFix = TRUE)

1.3.2 Experimenting with Color Mixtures

The colorMixtureVenn function from the sharpshootR package is a handy way to view simulated mixtures of 2-7 colors.

colorMixtureVenn(colors)

chips <- c('10YR 8/1', '2.5YR 3/6', '10YR 2/2')
colorMixtureVenn(chips)