magick パッケージの紹介

Sunday, Jun 13, 2021| Tags: R magick images

研究室のサーバには ImageMagick いうソフトをインストールしています。 ImageMagick は画像の編集するためのソフトです。 GIF, JPEG, PNG, PDF, TIFF などさまざまな画像ファイルの処理ができます。 基本的には, ImageMagickは CLI で使いますが, R 環境からでも使えます。

Rでは magick というパッケージを使います。

パッケージの読み込み

まずは実用なパッケージを読み込みます。

library(tidyverse) # データ処理や作図に使う関数はここにある
library(magick) # 画像処理に使う関数はここ

magick パッケージのほとんどは image_ から始まります。 第1引数 (image) は画像オブジェクトです。

画像の読み込みと情報表示

まずは画像ファイルの読み込みをします。 関数は image_read() です。 URL でも ファイル名でもOKです。

# ファイル名は URL でもOK
filename = "https://nagaremo.jp/ja/gallery/nokogiri01.jpg"
img = image_read(filename)

画像の情報は image_info() でみれます。

image_info(img)
## # A tibble: 1 x 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 JPEG    1080    810 sRGB       FALSE   283871 314x314

画像サイズ変更

画像サイズ変更の関数は image_resize() です。 geometry で画像サイズを指定します。

geometry = "WxH"

  • W Width 画像の幅は pixel か % で指定します。
  • H Height 画像の高さも pixel か % で指定します。

方がのサイズだけ指定した場合, 縦横のアスペクト比を 守りながら拡大・縮小します。

geometry の詳細は ImageMagick#geometry

# 幅を 500 pixel になるように
image_resize(img, geometry = "500x")

# 高さを 500 pixel になるよおうに
image_resize(img, geometry = "x500")

# 幅を 20% 縮小し, アスペクト比を維持
image_resize(img, geometry = "20%")

画像結合

つぎは2つの画像を縦に結合します。 まずは画像の読み込みと情報確認です。

filename1 = "https://nagaremo.jp/ja/gallery/nokogiri01.jpg"
filename2 = "https://nagaremo.jp/ja/gallery/urae01.jpg"
img1 = image_read(filename1)
img2 = image_read(filename2)
img1 %>% image_info()
## # A tibble: 1 x 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 JPEG    1080    810 sRGB       FALSE   283871 314x314
img2 %>% image_info()
## # A tibble: 1 x 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 JPEG    1080    810 sRGB       FALSE   110516 314x314

どちらも 1080x810 の JPEG です。 画像を結合したあと, 高さが 810 になるように縮小します。

img12 = image_append(c(img1, img2), stack = TRUE) 

この処理で画像を結合したが, 高かさは 2 x 810 = 1620 pixel です。

image_info(img12)
## # A tibble: 1 x 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 JPEG    1080   1620 sRGB       FALSE        0 314x314

image_resize() で縮小します。

img12 = image_resize(img12, geometry = "x810")
image_info(img12)
## # A tibble: 1 x 7
##   format width height colorspace matte filesize density
##   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
## 1 JPEG     540    810 sRGB       FALSE        0 314x314
img12

横に結合する場合, stack= FALSE にする。

image_append(c(img1, img2), stack = F) %>% 
  image_resize(geometry = "1000x")

画像に文字を追加する

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

filename1 = "https://nagaremo.jp/ja/gallery/nokogiri01.jpg"
img1 = image_read(filename1)

文字を追加するためには, image_annotate() をつかいます。

  • text には文字列
  • gravity には追加する文字列の位置を指定します。
    • north, south, east, west
    • northwest, northeast, southwest, southeast
    • center
  • location をつかって文字列を gravity で指定した位置からずらせます。
  • size はフォントの pixel サイズです。
  • font はフォント名です。これはOSに依存します。 研究室の場合は次を使ってください。
    • Noto Serif
    • Noto Sans
    • Noto Serif CJK jp
    • Noto Sans CJK jp
  • style は文字の書体です。italic 体を使いたいときに 指定します。bold 体は weight で指定します。
  • weight は文字の太さを設定できます。
    • Noto の weight は {100, 300, 400, 500, 700, 900} です。
      • 100: Thin
      • 300: Light
      • 400: Regular
      • 500: Medium
      • 700: Bold
      • 900: Black
  • color は文字の色です。色は英語, 16進法, RGBa で指定できます。
# 学名を埋め込む
species = "Sargassum macrocarpum"
image_annotate(img1, 
               text = species,
               gravity = "north",
               location = "+0+100",
               size = 50,
               font = "Noto Serif",
               style = "Italic",
               weight = 700,
               color = "black")

# 和名を埋め込む・フォント名に注意
wamei = "ノコギリモク"
image_annotate(img1, 
               text = wamei,
               gravity = "northwest",
               location = "+0+0",
               size = 50,
               font = "Noto Serif CJK jp",
               weight = 700,
               color = "black")

文字を見やすいようにするとき, 文字背景の色を変えたり, 文字の色を変えたりします。

まず, 文字背景のボックスをつくります。

# もとの画像の幅を抽出する
w = image_info(img1)$width
h = 100 # ボックスの高さ

# 背景の色を白 60% 透明度
wamei_background = image_blank(w, h, color = "rgba(255,255,255, 0.6")

和名を wamei_background についかする。

wamei = "ノコギリモク"
wamei_background = wamei_background %>% 
  image_annotate(text = wamei,
               gravity = "center",
               location = "+0+0",
               size = 50,
               weight = 700,
               font = "Noto Serif CJK JP",
               color = "black")  
image_composite(img1, wamei_background,
                operator = "atop",
                offset = "+0+0") 

文字の書体が変わる場合, そのつど image_annotate() をつかいます。

species = "Sargassum macrocarpum"
wamei = "ノコギリモク"
w = image_info(img1)$width
h = 80
background = image_blank(w, h, color = "rgba(255,255,255, 0.6")

background = background %>% 
  image_annotate(text = species,
               gravity = "west",
               location = "+10+0",
               size = 50,
               weight = 700,
               style = "italic",
               font = "Noto Serif",
               color = "black")  %>% 
  image_annotate(text = wamei,
               gravity = "east",
               location = "+10+0",
               size = 50,
               weight = 700,
               font = "Noto Serif CJK JP",
               color = "black")

image_composite(img1, background,
                operator = "atop",
                offset = "+0+0") 

4つの画像の結合

使用する画像を読み込みます。

filename1 = "https://nagaremo.jp/ja/gallery/nokogiri01.jpg"
filename2 = "https://nagaremo.jp/ja/gallery/urae01.jpg"
filename3 = "https://nagaremo.jp/ja/gallery/sargassum01.jpg"
filename4 = "https://nagaremo.jp/ja/gallery/seagrass-arikawa-beach.jpg"
img1 = image_read(filename1)
img2 = image_read(filename2)
img3 = image_read(filename3)
img4 = image_read(filename4)

画像ごとの説明文書を追加します。

text1 = "ノコギリモク"
text2 = "撮影中"
text3 = "アカモク場"
text4 = "アマモ場"

w = image_info(img1)$width
h = 80
background = image_blank(w, h, color = "rgba(255,255,255, 0.6")

b1 = background %>% 
  image_annotate(text = text1,
               gravity = "center",
               location = "+0+0",
               size = 50,
               weight = 700,
               font = "Noto Serif CJK JP",
               color = "black")
b2 = background %>% 
  image_annotate(text = text2,
               gravity = "center",
               location = "+0+0",
               size = 50,
               weight = 700,
               font = "Noto Serif CJK JP",
               color = "black")
b3 = background %>% 
  image_annotate(text = text3,
               gravity = "center",
               location = "+0+0",
               size = 50,
               weight = 700,
               font = "Noto Serif CJK JP",
               color = "black")
b4 = background %>% 
  image_annotate(text = text4,
               gravity = "center",
               location = "+0+0",
               size = 50,
               weight = 700,
               font = "Noto Serif CJK JP",
               color = "black")

img1 = image_composite(img1, b1)
img2 = image_composite(img2, b2)
img3 = image_composite(img3, b3)
img4 = image_composite(img4, b4)

画像の周りに 5x5 ピクセルの黒いふちをつけます。

img1 = img1 %>% image_border(color = "black", geometry = "5x5" )
img2 = img2 %>% image_border(color = "black", geometry = "5x5" )
img3 = img3 %>% image_border(color = "black", geometry = "5x5" )
img4 = img4 %>% image_border(color = "black", geometry = "5x5" )

2つの画像を横に結合してから, 結合したペアを縦に結合します。

img12 = image_append(c(img1, img2))
img34 = image_append(c(img3, img4))

縦に結合した画像は幅 1000 ピクセルに縮小したら完成です。

image_append(c(img12, img34), stack = T)%>% 
  image_resize(geometry = "1000x")

ところが, 外側の黒い部分は不要なので, image_trim() で削除します。

image_append(c(img12, img34), stack = T) %>% 
  image_trim() %>% 
  image_resize(geometry = "1000x")

完成した画像は image_write() で保存できます。

img1234 = image_append(c(img12, img34), stack = T) %>% 
  image_trim() %>% 
  image_resize(geometry = "1000x")

image_write(img1234, 
            path = "~/Downloads/2x2_images.png",
            format = "png")

もっと知りたいなら、連絡してください。

連絡先