【问题标题】:Control alpha blending / opacity of n overlapping areas控制 n 个重叠区域的 alpha 混合/不透明度
【发布时间】:2019-12-15 02:57:12
【问题描述】:

我很难理解(和控制)alpha 的混合 - 不幸的是,alpha 值不会简单地“加起来”(0.5 + 0.5 不是 1)。但我怎样才能做到这一点呢?

目的是定义重叠区域相对于观察总数的(绝对)灰度值。 请参见下面的示例。

我尝试设置scale_alpha(range = c(0,1))无济于事,可能是我没有正确使用它。

library(ggplot2)
library(ggforce)

grid_df = data.frame(x = c(1:2, 2.5), y = rep(1,3), r = 1)

ggplot()+
geom_circle(data = grid_df, mapping = aes(x0 = x,  y0 = y, r = r), alpha = 0.33, fill = 'black') + 
  coord_fixed() 

【问题讨论】:

  • 也许我不明白这个问题,因为在我看来,alpha 大约是 33%、66% 和 100%。你如何评价现在的阿尔法?或者你还有什么想要实现的吗?
  • 我的问题可能不够清楚。道歉。我想根据图像中的百分比设置不透明度 - 100% 将是黑色,即完全不透明度
  • @zx8754 我现在才看到这个链接。这是一篇不错的博文!!感谢分享
  • 是的,他们需要将名称更改为“酷有用”。

标签: r ggplot2 alpha


【解决方案1】:

首先,+1 给@JonSpring——这只是他们答案末尾的想法的扩展。如果你做一个sf 对象,你可以很容易地得到多边形的交点。你最终绘制的不是圆本身,而是分割相交部分的多边形。

从您的网格开始,为每一行创建一个点,将其转换为 sf 数据框,然后在 r 列中给定的半径处获取点的缓冲区。这会将每个点变成一个以该点坐标为中心的圆,并且对于不同的半径是灵活的。 3个圆之间有6个相交的多边形,如结果所示。

library(dplyr)
library(sf)
library(ggplot2)
library(ggforce)

grid_df <- data.frame(x = c(1:2, 2.5), y = rep(1,3), r = 1)

grid_sf <- grid_df %>%
  mutate(geometry = purrr::map2(x, y, ~st_point(c(.x, .y)))) %>%
  st_as_sf() %>%
  st_buffer(dist = .$r, nQuadSegs = 60) %>%
  st_intersection()

grid_sf
#> Simple feature collection with 6 features and 5 fields
#> geometry type:  GEOMETRY
#> dimension:      XY
#> bbox:           xmin: 0 ymin: 0 xmax: 3.5 ymax: 2
#> epsg (SRID):    NA
#> proj4string:    NA
#>       x y r n.overlaps origins                       geometry
#> 1   1.0 1 1          1       1 POLYGON ((1.5 0.1339746, 1....
#> 1.1 1.0 1 1          2    1, 2 POLYGON ((1.75 0.3386862, 1...
#> 2   2.0 1 1          1       2 MULTIPOLYGON (((2.258819 0....
#> 1.2 1.0 1 1          3 1, 2, 3 POLYGON ((2 1, 1.999657 0.9...
#> 2.1 2.0 1 1          2    2, 3 POLYGON ((3 1, 2.999657 0.9...
#> 3   2.5 1 1          1       3 MULTIPOLYGON (((3.5 1, 3.49...

使用来自st_intersectionn.overlaps 列来分配alpha。默认情况下,alpha 将从 0 缩放到 1,但我认为您实际上并不想要 0 alpha 用于圆圈的外部、非重叠部分,因此我对其进行缩放以获得最小 alpha。

alpha_range <- range(grid_sf$n.overlaps) / max(grid_sf$n.overlaps)

grid_sf  %>%
  ggplot() +
  geom_sf(aes(alpha = n.overlaps), fill = "black") +
  scale_alpha(range = alpha_range)

只是为了进一步扩展并使不同的多边形更加清晰,看看用离散的填充比例而不是 alpha:

grid_sf  %>%
  ggplot() +
  geom_sf(aes(fill = as.factor(n.overlaps))) +
  scale_fill_brewer(palette = "YlGnBu")

【讨论】:

    【解决方案2】:

    添加到@MKBakker 的答案,可以使用一个函数来预测任意数量的层和 alpha 值的结果 alpha:

    alpha_out <- function(alpha, num = 1) {
      result = alpha
      if(num == 1)  return(result)
      for(i in 2:num) { result = result + alpha * (1-result) }
      return (result)
    }
    
    alpha_out(0.33, 1)
    #[1] 0.33
    alpha_out(0.33, 2)
    #[1] 0.5511
    alpha_out(0.33, 3)
    #[1] 0.699237
    

    这使得更容易看到 alpha 通过更多层渐近接近 1。

    alpha_out(0.33, 40)
    #[1] 0.9999999
    

    如果有人认为 0.99 “足够接近”,则需要使用 0.8 才能达到三层

    alpha_out(0.8, 3)
    #[1] 0.992
    

    编辑:添加结果图表

    我们可以看到我们会从一系列 alpha 和层中得到什么结果:

    library(tidyverse)
    alpha_table <- 
      tibble(
        alpha = rep(0.01*1:99, 10),
        layers = rep(1:10, each = 99)
      )
    
    alpha_table <- alpha_table %>%
      rowwise() %>%
      mutate(result = alpha_out(alpha, layers))
    
    ggplot(alpha_table, aes(alpha, result, color = as_factor(layers),
                        group = layers)) +
    geom_line()
    

    我们还可以看到在给定每个层数的情况下,我们需要多少 alpha 才能通过组合不透明度的阈值。例如,对于给定的层数,要达到 0.99 的总不透明度需要多少 alpha。例如,对于 5 层,您需要 alpha = 0.61

    alpha_table %>%
      group_by(layers) %>%
      filter(result >= 0.99) %>%
      slice(1)
    ## A tibble: 10 x 3
    ## Groups:   layers [10]
    #   alpha layers result
    #   <dbl>  <int>  <dbl>
    # 1  0.99      1  0.99 
    # 2  0.9       2  0.99 
    # 3  0.79      3  0.991
    # 4  0.69      4  0.991
    # 5  0.61      5  0.991
    # 6  0.54      6  0.991
    # 7  0.49      7  0.991
    # 8  0.44      8  0.990
    # 9  0.41      9  0.991
    #10  0.37     10  0.990
    

    所有这一切都说明我认为没有一个简单的实现可以得到你正在寻找的东西。如果您希望重叠区域 100% 暗,您可以尝试以下方法:

    • 事后图像处理(也许可以使用 imagemagick)应用亮度曲线,使暗区 100% 变黑,并使其他区域缩放到您期望的暗度级别。

      李>
    • 将图形转换为sf 对象并分析形状以某种方式计算在任何给定点重叠的形状数量。然后,您可以手动将它们映射到您想要的黑暗级别。

    【讨论】:

    • 我们可以只 fork ggplot2 将 alpha 混合的公式更改为简单的加法吗?
    【解决方案3】:

    可以使用以下方法添加Alpha(https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending

    两个合并形状的 alpha 计算如下:
    A(out) = A(src) + A(dst) * 1-A(src)

    因此,对于 A(src) = A(dst) = 0.33,我们得到:

    x = 0.33  
    y = x + x*(1-x)  
    y
    

    [1] 0.5511

    如果我们有三个形状,A = 0.33,我们归纳:

    y = x + x*(1-x) + x*(1-(x + x*(1-x)))
    y
    

    [1] 0.699237

    我可以继续讨论在将 2 或 3 个形状相加时哪些值会产生 1,但最有用的评论是 alpha 不是以相加方式组合的。

    【讨论】:

    • 当我尝试一些不同的值时,这是一个复制/粘贴错误。在上面的例子中,x=0.33
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多