Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add half-value Munsell chips beyond 2.5 #319

Merged
merged 9 commits into from
Oct 4, 2024
5 changes: 5 additions & 0 deletions R/munsell2rgb.R
Original file line number Diff line number Diff line change
Expand Up @@ -382,11 +382,16 @@ munsell2rgb <- function(the_hue, the_value, the_chroma, alpha = 1, maxColorValue
# plyr::join() 2x faster than base::merge
# data.table::merge() (with conversion to/from) 5x faster than base::merge()


## TODO: maybe more efficient with keys
# round-trip through data.table is still faster
d <- data.table::as.data.table(d)
munsell <- data.table::as.data.table(munsell)


## TODO: optimize by first filtering full lookup table on e.g. hue


# join
res <- merge(d, munsell, by = c('hue','value','chroma'), all.x = TRUE, sort = FALSE)

Expand Down
Binary file modified data/munsell.rda
Binary file not shown.
36 changes: 30 additions & 6 deletions misc/utils/Munsell/interpolate-spectra.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
library(lattice)
library(tactile)
library(pbapply)
library(purrr)
library(reshape2)

# load simplified spectra
Expand Down Expand Up @@ -47,7 +47,7 @@ interpolateOddChromaSpectra <- function(i) {
# short circuit: 0 candidates for interpolation
if(length(s.chroma) < 1)
return(NULL)


# setup interpolation function: natural splines
# fit is exact at training points
Expand Down Expand Up @@ -89,7 +89,7 @@ interpolateOddChromaSpectra <- function(i) {
}

# do interpolation
mm <- pblapply(m, interpolateOddChromaSpectra)
mm <- map(m, .f = interpolateOddChromaSpectra, .progress = TRUE)

# combine
mm <- do.call('rbind', mm)
Expand All @@ -109,6 +109,16 @@ xyplot(reflectance ~ chroma | factor(wavelength), data=s,
par.settings = tactile.theme()
)

idx <- which(m.final$hue %in% c('2.5YR') & m.final$value == 4)
s <- m.final[idx, ]

xyplot(reflectance ~ chroma | factor(wavelength), data=s,
type='b', as.table=TRUE,
scales = list(y = list(tick.number = 10)),
par.settings = tactile.theme()
)



# check for reflectance <= 0
m.final[m.final$reflectance <= 0, ]
Expand All @@ -133,7 +143,7 @@ m.final$reflectance[idx] <- min(m.final$reflectance[-idx])


## check: OK
s <- subset(m.final, subset = hue == '2.5YR' & value == 4 & chroma %in% 2:4)
s <- subset(m.final, subset = hue == '5YR' & value == 4 & chroma %in% 2:4)

xyplot(reflectance ~ wavelength, data = s,
groups = munsell, type='b',
Expand All @@ -143,6 +153,15 @@ xyplot(reflectance ~ wavelength, data = s,
)


s <- subset(m.final, subset = hue == '2.5Y' & value == 4 & chroma %in% 2:4)

xyplot(reflectance ~ wavelength, data = s,
groups = munsell, type='b',
scales = list(y = list(tick.number = 10)),
auto.key=list(lines=TRUE, points=FALSE, cex=1, space='top', columns = 3),
par.settings = tactile.theme()
)



## interpolate 2.5 value
Expand Down Expand Up @@ -195,7 +214,7 @@ interpolateValueSpectra <- function(i) {


# do interpolation
mm <- pblapply(m, interpolateValueSpectra)
mm <- map(m, .f = interpolateValueSpectra, .progress = TRUE)

# combine
mm <- do.call('rbind', mm)
Expand Down Expand Up @@ -238,6 +257,11 @@ save(munsell.spectra, file = '../../../data/munsell.spectra.rda', compress = 'xz
save(munsell.spectra.wide, file = '../../../data/munsell.spectra.wide.rda', compress = 'xz')

# cleanup
unlink(c('interpolated-Munsell-spectra-wide.rds', 'interpolated-Munsell-spectra.rds', 'simplified-Munsell-spectra.rds'))
unlink(
c('interpolated-Munsell-spectra-wide.rds',
'interpolated-Munsell-spectra.rds',
'simplified-Munsell-spectra.rds'
)
)


41 changes: 40 additions & 1 deletion misc/utils/Munsell/local-functions.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,47 @@ interpolateChroma <- function(m.i) {
}


## TODO: consider re-writing for entire range, and splinefun() based interpolation
# 2024-09-26
# re-write of interpolateValue() -> now safely interpolates all 0.5 values
interpolateValue2 <- function(m.i) {

# can only proceed with >=2 rows
# some combinations of hue, value, chroma have 1 row.
# there will be other combinations created by split() with 0 rows
if(nrow(m.i) < 2) {
return(NULL)
}

# linear interpolation ~ munsell value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update comment

# x ~ V
s.1 <- splinefun(m.i$V, m.i$x)
# y ~ V
s.2 <- splinefun(m.i$V, m.i$y)
# Y ~ V
s.3 <- splinefun(m.i$V, m.i$Y)

# all odd values
new.V <- seq(from = min(m.i$V) + 0.5, to = max(m.i$V) - 0.5, by = 1)

# combine interpolated values into data.frame
# H, C are constant
m.new <- data.frame(
H = m.i$H[1],
V = new.V,
C = m.i$C[1],
p1 = s.1(new.V),
p2 = s.2(new.V),
p3 = s.3(new.V)
)

names(m.new) <- c('H', 'V', 'C', 'x', 'y', 'Y')

# only return new rows
return(m.new)
}


## NOTE: this can only interpolate between two integer values
# 2022-03-29
# for now only interpolating 2.5 value
# usually interpolating xyY,
Expand Down
6 changes: 4 additions & 2 deletions misc/utils/Munsell/main.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
## Code / Data related to preparation of Munsell color interpretation in aqp
## 2022-03-29
## 2024-09-26
## D.E. Beaudette, A.G. Brown

# make Munsell and related LUT
# add neutral chips
# + neutral chips
# + odd chroma
# + 0.5 value
# xyY [C] -> XYZ [D65] -> sRGB -> CIELAB
source('prepare-munsell-LUT.R')

Expand Down
Binary file added misc/utils/Munsell/munsell-LUT-2024-09-25.rds
Binary file not shown.
Loading
Loading