0

假设我有一张这样的图表,作为图像:

在此处输入图像描述

我想提取它的颜色并找到最接近的颜色grDevices::colors(),可以在这里看到

head(grDevices::colors())
[1] "white"         "aliceblue"     "antiquewhite"  "antiquewhite1" "antiquewhite2" "antiquewhite3"

最简单的输出是这些颜色的向量。

更高级的输出将是一个带有真实颜色代码的 data.frame、“圆角”颜色(即 的一部分grDevices::colors())、它覆盖的图像表面的百分比以及其覆盖区域的重心坐标。

一个超级精美的输出会将这些颜色名称覆盖在原始图表上,或/和构建一个新的点图,将点放置在这些中心位置,颜色名称作为文本标签。

超精美的输出将提出现有调色板中最接近的匹配。

4

1 回答 1

0

tldr :get_named_colors("https://i.stack.imgur.com/zdyNO.png")使用底部定义的函数。


我们将在 R 中加载图像,将其转换为长 rgb 格式,获取命名颜色的 rgb 值并将它们以相同格式放置,然后计算所有相关距离并为图像的每种颜色保持最小值,从那里我们得到我们的输出。

library(ggplot2)
library(dplyr)      
library(png)

我们的候选人:

rgb_named_colors <- t(col2rgb(grDevices::colors())/255)
head(rgb_named_colors,3)
#            red     green      blue
# [1,] 1.0000000 1.0000000 1.0000000
# [2,] 0.9411765 0.9725490 1.0000000
# [3,] 0.9803922 0.9215686 0.8431373

我们的颜色:

img     <- readPNG("https://i.stack.imgur.com/zdyNO.png")
dim(img) # [1] 476 746   3
# it's a 3d matrix, let's convert it to long format
rgb_img <- apply(img,3,c)
colnames(rgb_img) <- c("red","green","blue")
head(rgb_img,3)
# red     green      blue
# [1,] 0.9803922 0.9803922 0.9803922
# [2,] 0.9803922 0.9803922 0.9803922
# [3,] 0.9803922 0.9803922 0.9803922

dim(unique(rgb_img)) # [1] 958   3

我们有 958 种颜色,有点多,我们需要过滤掉那些出现率低的颜色,我们设置了0.5%img 像素的截止值。

rgb_img_agg <-
  rgb_img %>%
  as_tibble %>%
  group_by_all %>%
  count %>%
  filter(n > dim(img)[1]* dim(img)[2] *0.5/100)

效果如何?

dim(rgb_img_agg) # [1] 11  4

好多了。

head(rgb_img_agg,3)
# # A tibble: 3 x 4
# # Groups:   red, green, blue [3]
#          red     green      blue     n
#        <dbl>     <dbl>     <dbl> <int>
# 1 0.04705882 0.2627451 0.5137255  2381
# 2 0.27843137 0.5568627 0.7803922 29353
# 3 0.37254902 0.7450980 0.2549020  2170

对于所有图像颜色,我们计算到命名颜色的距离并保持最小值

output <- apply(rgb_img_agg[1:3],1, function(row_img)
  grDevices::colors()[which.min(
  apply(rgb_named_colors,1,function(row_named)
    dist(rbind(row_img,row_named))))])

ouput
# [1] "dodgerblue4" "steelblue3"  "limegreen"   "olivedrab"   "gray80"      "olivedrab1"  "chocolate3"  "chocolate1" 
# [9] "ghostwhite"  "gray98"      "white" 

有用!现在让我们用一个图例显示我们所有的颜色:

ggplot(tibble(named_color=output),aes(named_color,fill=factor(named_color,levels=output))) + geom_bar() +
    scale_fill_manual(values = output)

现在我们把所有东西都放在一个函数中:

get_named_colors <- function(path, cutoff = 0.5){
  library(dplyr)
  library(ggplot2)
  library(png)
  # named colors
  rgb_named_colors <- t(col2rgb(grDevices::colors())/255)

  # colors from path
  img     <- readPNG(path)
  rgb_img <- apply(img,3,c)
  colnames(rgb_img) <- c("red","green","blue")
  rgb_img_agg <-
    rgb_img %>%
    as_tibble %>%
    group_by_all %>%
    count %>%
    filter(n > dim(img)[1]* dim(img)[2] *cutoff/100)

  # distances
  output <- apply(rgb_img_agg[1:3],1, function(row_img)
    grDevices::colors()[which.min(
      apply(rgb_named_colors,1,function(row_named)
        dist(rbind(row_img,row_named))))])

  p <- ggplot(tibble(named_color=output),aes(named_color,fill=factor(named_color,levels=output))) + geom_bar() +
    scale_fill_manual(values = output)
  print(p)

  output
}

如果我发现如何实现花哨的功能,我可能会更新。

于 2018-07-19T12:03:26.590 回答