からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

magick::image_scale関数による画像変形

はじめに

 R言語で画像処理を行うmagickパッケージを確認します。
 この記事では、image_scale()により画像を変形します。

【この記事の内容】

magick::image_scale関数

 magickパッケージの画像サイズを整形する関数image_scale()を確認します。より細かく設定したい場合はimage_resize()の方がいいようですが(?)扱いません。

 利用するパッケージを読み込みます。

# 利用パッケージ
library(magick)
library(tidyverse)

 この記事では、基本的にパッケージ名::関数名()の記法を使うので、パッケージを読み込む必要はありません。ただし、作図コードがごちゃごちゃしないようにパッケージ名を省略しているため、ggplot2は読み込む必要があります。
 また、ネイティブパイプ演算子|>を使っています。magrittrパッケージのパイプ演算子%>%に置き換えても処理できますが、その場合はmagrittrも読み込む必要があります。

画像の作成

 まずは、例として利用するための画像ファイルを作成します。 z = x + yのヒートマップを例とします。

 x軸とy軸の値を指定して、z軸の値を計算します。

# x軸とy軸の値を作成
x_vals <- seq(from = 1, to = 4, by = 1)
y_vals <- seq(from = 1, to = 3, by = 1)

# 作図用のデータフレームを作成
df <- tidyr::expand_grid(x = x_vals, y = y_vals) |> # 格子点を作成
  dplyr::mutate(z = x + y)
df
## # A tibble: 12 × 3
##        x     y     z
##    <dbl> <dbl> <dbl>
##  1     1     1     2
##  2     1     2     3
##  3     1     3     4
##  4     2     1     3
##  5     2     2     4
##  6     2     3     5
##  7     3     1     4
##  8     3     2     5
##  9     3     3     6
## 10     4     1     5
## 11     4     2     6
## 12     4     3     7

 x軸の値をx_vals、y軸の値をy_valsを作成して、x_vals, y_valsの格子状の点(全ての組み合わせ)をexpand_grid()で作成しx軸とy軸の値を足します。

 ヒートマップを作成します。

# ヒートマップを作成
g <- ggplot(data = df, mapping = aes(x = x, y = y, fill = z)) + 
  geom_tile(show.legend = FALSE) + # ヒートマップ
  geom_text(mapping = aes(label = paste0("(", x, ", ", y, ")")), color = "white", size = 10) + # 座標ラベル
  scale_x_continuous(breaks = x_vals) + 
  scale_y_continuous(breaks = y_vals) + 
  scale_fill_gradient(low ="gold", high = "red") + # グラデーション
  coord_equal(clip = "off", expand = FALSE) + # アスペクト比
  labs(title = "Heatmap", 
       subtitle = "(x, y)")
g

ヒートマップ

 geom_tile()でヒートマップを描画します。格子点を渡す必要があります。
 (資料作成時の仕様がよく分からず、この図と書き出し・読み込み後の図の体裁が変わってますが気にしないでください…)

 作成したグラフを画像ファイルとして書き出します。

# 画像を書き出し
ggplot2::ggsave(
  filename = "heatmap.png", plot = g, 
  width = max(x_vals)*200, height = max(y_vals)*200, units = "px", dpi = 100
)

 ggsave()でpngファイルとして保存します。

画像サイズの変換

 では、image_scale()を利用して画像サイズを変形する際の仕様(指定方法)を確認していきます。

 画像ファイルを読み込みます。

# 画像を読み込み
pic_data <- magick::image_read(path = "heatmap.png")
pic_data

元の画像

 image_read()にファイルパスを指定して、画像ファイルを読み込みます。

 画像情報を確認します。

# 画像情報を取得
pic_info <- magick::image_info(image = pic_data)
pic_info
## # A tibble: 1 × 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 PNG      800    600 sRGB       FALSE    26977 39x39

 image_info()で画像サイズなどを確認できます。
 横サイズ(横方向のピクセル数)が800、縦サイズ(縦方向のピクセル数)が600なのが分かります。

 image_scale()geometry引数に変形後のサイズを指定します。

 横サイズを指定する場合は、文字列でサイズを指定します。

# 横サイズを指定してリサイズ:アスペクト比固定
pic_scaled_w <- magick::image_scale(image = pic_data, geometry = "700")
pic_scaled_w |> 
  magick::image_info()
pic_scaled_w
## # A tibble: 1 × 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 PNG      700    525 sRGB       FALSE        0 39x39

横サイズを700に変形

 縦横比が保たれるように縦サイズが決まります。

 縦サイズを指定する場合は、xの後にサイズを指定します。

# 縦サイズを指定してリサイズ:アスペクト比固定
pic_scaled_h <- magick::image_scale(image = pic_data, geometry = "x700")
pic_scaled_h |> 
  magick::image_info()
pic_scaled_h
## # A tibble: 1 × 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 PNG      933    700 sRGB       FALSE        0 39x39

縦サイズを700に変形

 縦横比が保たれるように横サイズが決まります。

 xの前に横サイズの上限、後ろに縦サイズの上限を指定すると、それぞれの値を超えない範囲で縦横比を保って変形します。

# 縦横サイズを指定してリサイズ:アスペクト比固定
pic_scaled_wh <- magick::image_scale(image = pic_data, geometry = "750x750")
pic_scaled_wh |> 
  magick::image_info()
pic_scaled_wh
## # A tibble: 1 × 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 PNG      750    563 sRGB       FALSE        0 39x39

縦横サイズの上限を750に変形

 横サイズと縦サイズがそれぞれ750を超えていないのが分かります。

 縦横比を保たずに値を指定する場合は、文字列の最後に!を付けます。

# 横サイズを指定してリサイズ:アスペクト比変更
pic_scaled_wh <- magick::image_scale(image = pic_data, geometry = "750x750!")
pic_scaled_wh |> 
  magick::image_info()
pic_scaled_wh
## # A tibble: 1 × 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 PNG      750    750 sRGB       FALSE        0 39x39

縦横サイズを750に変形

 横サイズと縦サイズがそれぞれ750になっているのが分かります。

 さらに、横x縦+x+yと指定する方法もあるのですが、よく分からなかったので飛ばします。

 この記事では、magickパッケージのimage_scale()を解説しました。次の記事では、magickパッケージを使ってアニメーションを作成します。

参考

おわりに

 記事上だと最後以外は変形されているのか分かりませんね、、、手元の資料では分かったんです。一応アスペクト比が変わっていないだろうことと、画像情報を見るとサイズが変わっていることが分かりますし、この記事はおまけのおまけのようなものなので、これでよしとします。

【次の内容】

www.anarchive-beta.com