Charada: Você pode abrir o seu caminho para a liberdade?

Charada: Você pode abrir o seu caminho para a liberdade? 1

[ad_1]

[Esteartigofoipublicadopelaprimeiravezem[Thisarticlewasfirstpublishedon Posts | Joshua Cook, e gentilmente contribuiu para os R-blogueiros]. (Você pode relatar um problema sobre o conteúdo desta página aqui)


Deseja compartilhar seu conteúdo com R-blogueiros? clique aqui se você tiver um blog ou aqui se não tiver.

Riddler Express da FiveThirtyEight

Dakota Jones está de volta em ação. Após o fracasso na tentativa de viver com um site de cupom de desconto, ele mudou seu rumo. Em sua busca para localizar o Templo de
Diametra, ela encontrou outro cristal altamente simétrico. Contudo,
agentes nefastos novamente descobriram seus planos, e agora Dakota
e o cristal não está em lugar algum.

E assim, você deve recriar novamente o cristal usando os dados de
Scanner a laser de Dakota. Como lembrete, o scanner pega um objeto 3D
e registra fatias transversais 2D ao longo da terceira dimensão.
Aqui está o arquivo de animação em loop que o scanner produziu para o
cristal desta vez:

Charada: Você pode abrir o seu caminho para a liberdade? 2

Que tipo de forma tridimensional é o cristal? Sem pressão –
Dakota Jones, ou seja, o mundo inteiro, conta com você para localizar o
templo perdido!


Plano

Meu plano é ler as fatias do GIF, extrair as informações como
uma máscara binária, identifique os cantos das maks e plote esses cantos
no espaço 3D.

Configuração

knitr::opts_chunk$set(echo = TRUE, comment = "#>")
library(plotly)
library(htmlwidgets)
library(tidyverse)
theme_set(theme_minimal())

Preparando os dados da imagem

Eu li os dados da imagem GIF usando o read.gif() função do
Pacote ‘caTools’.

gif_path 
#> Warning in caTools::read.gif(gif_path): write.gif: file 'assets/crystal_538.gif'
#> contains multiple color-maps. Use 'frame' > 0.

A imagem está contida como uma matriz 3D no image slot. A imagem
matriz é numérica em que cada número corresponde a uma cor na fatia.

names(gif)
#> [1] "image" "col" "transparent" "comment"
dim(gif$image)
#> [1] 558 586 101
gif$image[1:5, 1:5, 1:3]
#> , , 1
#>
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0 0 0 0 0
#> [2,] 0 0 0 0 0
#> [3,] 0 0 0 0 0
#> [4,] 0 0 0 0 0
#> [5,] 0 0 0 0 0
#>
#> , , 2
#>
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 2 2 2 2 2
#> [2,] 2 2 2 2 2
#> [3,] 2 2 2 2 2
#> [4,] 2 2 2 2 2
#> [5,] 2 2 2 2 2
#>
#> , , 3
#>
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1 1 1 1 1
#> [2,] 1 1 1 1 1
#> [3,] 1 1 1 1 1
#> [4,] 1 1 1 1 1
#> [5,] 1 1 1 1 1

O built-in image() A função pode plotar uma matriz de valores numéricos.

image(gif$image[, , 21])

Charada: Você pode abrir o seu caminho para a liberdade? 4

Eu esperava encontrar apenas duas cores, o primeiro e o segundo plano, mas
a borda do primeiro plano e do fundo às vezes tinha um leve
cor diferente.

table(gif$image[, , 20])
#>
#> 0 1 2
#> 38164 288012 812
table(gif$image[, , 21])
#>
#> 0 1 2 3
#> 40000 802 285986 200
table(gif$image[, , 22])
#>
#> 0 1 2
#> 41184 285012 792

Felizmente, o primeiro plano sempre teve a cor 0. Portanto, eu fiz um
cópia do gif$image onde todos os 0 valores foram TRUE e o resto
estavam FALSE.

img 

Finalmente, o primeiro e o último quadro estão vazios, então eu os removi.

img 

“Arrumar” os dados da imagem

Eu queria colocar os dados da imagem em um formato organizado, para que cada linha fosse um
ponto de dados com colunas x, ye z (a fatia do GIF) para o
coordenadas do ponto de dados e uma coluna value para o valor (seja
TRUE ou FALSE) do ponto. Isso foi feito pelo get_tidy_xy()
funciton que leva um índice para o qual fatiar img.

Então, eu precisava pegar apenas os cantos da máscara. Felizmente, isso foi
fácil porque todos os shages individuais eram retângulos. Portanto, eu
poderia apenas filtrar os pontos no mínimo e no máximo x valores
e então o mínimo e o máximo y valores. Isso foi feito por
get_mask_corners() que ocupa um quadro de dados organizado como o produzido por
get_tidy_xy().

Ambas as funções foram usadas em conjunto para produzir o tidy_img
mexer.

get_tidy_xy %
as_tibble() %>%
mutate(y = 1:n()) %>%
pivot_longer(-y, names_to = "x", values_to = "value") %>%
mutate(x = as.numeric(x))
}
get_mask_corners %
filter(value) %>%
filter(x == min(x) | x == max(x)) %>%
filter(y == min(y) | y == max(y))
}
tidy_img %
mutate(xy = map(z, get_tidy_xy),
xy = map(xy, get_mask_corners)) %>%
unnest(xy)
tidy_img
#> # A tibble: 396 x 4
#> z y x value
#>    
#> 1 1 278 46 TRUE
#> 2 1 278 541 TRUE
#> 3 1 281 46 TRUE
#> 4 1 281 541 TRUE
#> 5 2 275 49 TRUE
#> 6 2 275 538 TRUE
#> 7 2 284 49 TRUE
#> 8 2 284 538 TRUE
#> 9 3 273 51 TRUE
#> 10 3 273 536 TRUE
#> # … with 386 more rows

Usei a biblioteca ‘ggforce’ para plotar as primeiras camadas, individualmente,
antes de ir para 3D.

tidy_img %>%
filter(z %in% 1:9) %>%
ggplot(aes(x = x, y = y, group = z)) +
facet_wrap(~ z) +
ggforce::geom_shape() +
scale_x_continuous(breaks = c(100, 300, 500)) +
scale_y_continuous(breaks = c(100, 300, 500)) +
theme(
panel.grid = element_line()
) +
labs(x = "x", y = "y",
title = "Surfaces through the image",
subtitle = "Each plot is a slice of the gif")

Charada: Você pode abrir o seu caminho para a liberdade? 6

Em vez de retângulos bonitos, isso produzia uma forma de gravata borboleta. Isso foi
por causa da ordem dos pontos – eles não estavam na ordem correta
para desenhar um retângulo, mas o ponto superior esquerdo foi seguido pelo
ponto inferior direito, causando a diagonal. Portanto, o
arrange_tidy_xy() função apenas reorganiza cada coordenada para
desenhe um retângulo.

arrange_tidy_xy %
group_by(z) %>%
nest() %>%
mutate(data = map(data, arrange_tidy_xy)) %>%
unnest(data)
tidy_img
#> # A tibble: 396 x 4
#> # Groups: z [99]
#> z y x value
#>    
#> 1 1 278 46 TRUE
#> 2 1 278 541 TRUE
#> 3 1 281 541 TRUE
#> 4 1 281 46 TRUE
#> 5 2 275 49 TRUE
#> 6 2 275 538 TRUE
#> 7 2 284 538 TRUE
#> 8 2 284 49 TRUE
#> 9 3 273 51 TRUE
#> 10 3 273 536 TRUE
#> # … with 386 more rows
tidy_img %>%
filter(z %in% round(seq(1, 99, length.out = 25))) %>%
ggplot(aes(x = x, y = y, group = z)) +
facet_wrap(~ z) +
ggforce::geom_shape() +
scale_x_continuous(breaks = c(100, 300, 500)) +
scale_y_continuous(breaks = c(100, 300, 500)) +
theme(
panel.grid = element_line()
) +
labs(x = "x", y = "y",
title = "Surfaces through the image",
subtitle = "Each plot is a slice of the gif")

Charada: Você pode abrir o seu caminho para a liberdade? 8

Plotagem 3D

Por fim, pude plotar os pontos em 3D para criar a forma de “Dakota
Jones ‘crystal “, como o Riddle solicita.

plot_ly(data = tidy_img, x = ~x, y = ~y, z = ~z, size = 1,
mode = "markers", opacity = 1.0, type = "scatter3d")



plot_ly(data = tidy_img, x = ~x, y = ~y, z = ~z, size = 1,
mode = "line", opacity = 0.5, type = "scatter3d")



plot_ly(data = tidy_img, x = ~x, y = ~y, z = ~z, type = "mesh3d")



 

 



[ad_2]