gpt4 book ai didi

r - 使用自定义图像的 3D 散点图

转载 作者:太空狗 更新时间:2023-10-29 17:47:30 26 4
gpt4 key购买 nike

我正在尝试使用 ggplotggimage 创建带有自定义图像的 3D 散点图。它在 2D 中运行良好:

library(ggplot2)
library(ggimage)
library(rsvg)

set.seed(2017-02-21)
d <- data.frame(x = rnorm(10), y = rnorm(10), z=1:10,
image = 'https://image.flaticon.com/icons/svg/31/31082.svg'
)

ggplot(d, aes(x, y)) +
geom_image(aes(image=image, color=z)) +
scale_color_gradient(low='burlywood1', high='burlywood4')

enter image description here

我尝试了两种创建 3D 图表的方法:

  1. plotly - 这目前不适用于 geom_image,尽管它已作为 future 请求排队。

  2. gg3D - 这是一个 R 包,但我无法让它很好地处理自定义图像。以下是这些库的最终组合方式:

library(ggplot2)
library(ggimage)
library(gg3D)

ggplot(d, aes(x=x, y=y, z=z, color=z)) +
axes_3D() +
geom_image(aes(image=image, color=z)) +
scale_color_gradient(low='burlywood1', high='burlywood4')

enter image description here

如有任何帮助,我们将不胜感激。如果那里存在解决方案,我可以使用 python 库、javascript 等。

最佳答案

这是一个将图像转换为数据帧的 hacky 解决方案,其中每个像素都变成我们发送到 plotly 中的体素(?)。它基本上可以工作,但还需要做更多的工作才能:

1) 进一步调整图像(使用侵 eclipse 步骤?)以排除更多的低 alpha 像素

2) 在 plotly 中使用请求的颜色范围

第一步:导入图片并调整大小,过滤掉透明或部分透明的像素

library(tidyverse)
library(magick)
sprite_frame <- image_read("coffee-bean-for-a-coffee-break.png") %>%
magick::image_resize("20x20") %>%
image_raster(tidy = T) %>%
mutate(alpha = str_sub(col, start = 7) %>% strtoi(base = 16)) %>%
filter(col != "transparent",
alpha > 240)

编辑:添加该 block 的结果以防对任何人有用:

sprite_frame <- 
structure(list(x = c(13L, 14L, 10L, 11L, 12L, 13L, 14L, 15L,
16L, 17L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 7L,
8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 6L, 7L, 8L, 9L,
10L, 11L, 12L, 13L, 14L, 15L, 16L, 5L, 6L, 7L, 8L, 9L, 10L, 11L,
12L, 13L, 14L, 15L, 19L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L,
13L, 14L, 19L, 20L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L,
13L, 18L, 19L, 20L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 17L,
18L, 19L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 15L, 16L, 17L, 18L, 19L,
2L, 3L, 4L, 5L, 6L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 2L, 3L,
4L, 5L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 1L, 2L, 3L, 9L,
10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 1L, 2L, 7L, 8L,
9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 2L, 6L, 7L, 8L, 9L,
10L, 11L, 12L, 13L, 14L, 15L, 16L, 5L, 6L, 7L, 8L, 9L, 10L, 11L,
12L, 13L, 14L, 15L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L,
14L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 4L, 5L, 6L,
7L, 8L, 9L, 10L, 11L, 6L, 7L, 8L), y = c(1L, 1L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L,
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L,
5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L,
6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 8L, 8L,
8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L, 9L,
9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L, 10L,
10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 11L, 11L, 11L,
11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L,
12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L,
13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L,
14L, 14L, 14L, 14L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 15L,
15L, 15L, 15L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L,
16L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 18L,
18L, 18L, 18L, 18L, 18L, 18L, 18L, 18L, 18L, 19L, 19L, 19L, 19L,
19L, 19L, 19L, 19L, 20L, 20L, 20L), col = c("#000000f6", "#000000fd",
"#000000f4", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000f8", "#000000f4", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000fd", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000f9", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000fd",
"#000000f4", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000fa", "#000000ff", "#000000ff", "#000000f6", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000fb", "#000000ff", "#000000ff",
"#000000ff", "#000000f3", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000fa", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000f1", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000f3",
"#000000ff", "#000000ff", "#000000ff", "#000000f6", "#000000f9",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000f5", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000f5",
"#000000fc", "#000000ff", "#000000fd", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000f3", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000ff",
"#000000ff", "#000000f5", "#000000f8", "#000000ff", "#000000ff",
"#000000ff", "#000000ff", "#000000ff", "#000000ff", "#000000f4",
"#000000f1", "#000000fe", "#000000f7"), alpha = c(246L, 253L,
244L, 255L, 255L, 255L, 255L, 255L, 255L, 248L, 244L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 253L, 255L, 255L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 249L, 255L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 253L, 244L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 250L, 255L,
255L, 246L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 251L,
255L, 255L, 255L, 243L, 255L, 255L, 255L, 255L, 255L, 255L, 250L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 241L, 255L,
255L, 255L, 255L, 255L, 243L, 255L, 255L, 255L, 246L, 249L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 245L, 255L, 255L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 245L, 252L, 255L, 253L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 243L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L,
255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 255L, 245L, 248L,
255L, 255L, 255L, 255L, 255L, 255L, 244L, 241L, 254L, 247L)), row.names = c(NA,
-210L), class = "data.frame")

这是它的样子:

ggplot(sprite_frame, aes(x,y, fill = col)) + 
geom_raster() +
guides(fill = F) +
scale_fill_identity()

enter image description here

第 2 步:将这些像素作为体素引入

pixels_per_image <- nrow(sprite_frame)
scale <- 1/40 # How big should a pixel be in coordinate space?

set.seed(2017-02-21)
d <- data.frame(x = rnorm(10), y = rnorm(10), z=1:10)
d2 <- d %>%
mutate(copies = pixels_per_image) %>%
uncount(copies) %>%
mutate(x_sprite = sprite_frame$x*scale + x,
y_sprite = sprite_frame$y*scale + y,
col = rep(sprite_frame$col, nrow(d)))

我们可以使用 ggplot 在二维空间中绘制:

ggplot(d2, aes(x_sprite, y_sprite, z = z, alpha = col, fill = z)) + 
geom_tile(width = scale, height = scale) +
guides(alpha = F) +
scale_fill_gradient(low='burlywood1', high='burlywood4')

enter image description here

或者带入plotly。请注意,绘图 3d 散点目前不支持可变不透明度,因此图像当前显示为实心椭圆,直到您将其放大到一个 Sprite 。

library(plotly)
plot_ly(d2, x = ~x_sprite, y = ~y_sprite, z = ~z,
size = scale, color = ~z, colors = c("#FFD39B", "#8B7355")) %>%
add_markers()

enter image description here


编辑:尝试绘制 mesh3d 方法

似乎另一种方法是将 SVG 字形转换为 plotly 中 mesh3d 表面的坐标。

我最初尝试这样做是不切实际的手动操作:

  1. 在 Inkscape 中加载 SVG 并使用“展平贝塞尔曲线”选项在没有贝塞尔曲线的情况下近似形状。
  2. 导出具有原始坐标的 SVG 和十字指。我是 SVG 的新手,看起来输出通常是绝对点和相对点的混合体。在这种情况下更加复杂,因为字形有两个断开连接的部分。
  3. 将坐标重新格式化为数据框,以便使用 ggplot2 或 plotly 进行绘图。

例如,以下坐标表示半个 bean ,我们可以将其转换为另一半:

library(dplyr)
half_bean <- read.table(
header = T,
stringsAsFactors = F,
text = "x y
153.714 159.412
95.490016 186.286
54.982625 216.85
28.976672 247.7425
14.257 275.602
0.49742188 229.14067
5.610375 175.89737
28.738141 120.85839
69.023 69.01
128.24827 24.564609
190.72412 2.382875
249.14492 3.7247031
274.55165 13.610674
296.205 29.85
296.4 30.064
283.67119 58.138937
258.36 93.03325
216.39731 128.77994
153.714 159.412"
) %>%
mutate(z = 0)

other_half <- half_bean %>%
mutate(x = 330 - x,
y = 330 - y,
z = z)

ggplot() + coord_equal() +
geom_path(data = half_bean, aes(x,y)) +
geom_path(data = other_half, aes(x,y))

enter image description here

虽然这在 ggplot 中看起来不错,但我无法让凹面部分在 plotly 中正确显示:

library(plotly)
plot_ly(type = 'mesh3d',
split = c(rep(1, 19), rep(2, 19)),
x = c(half_bean$x, other_half$x),
y = c(half_bean$y, other_half$y),
z = c(half_bean$z, other_half$z)
)

enter image description here

关于r - 使用自定义图像的 3D 散点图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55308428/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com