京橋のバイオインフォマティシャンの日常

データ分析、コマンドライン、プログラミングについての技術資料・自己アップデート・悩み事などをまとめています。最近、ディープラーニング関連のR言語の資料をまとめるべく注力してます。

R/rvestを使って、Google画像検索で画像サムネイルを取得して、機械学習・ディープラーニング用の4次元アレイデータに変換するTips

手作業をできるだけ抑えて、 機械学習・ディープラーニング(DL)用の画像データを手っ取り早く取得したい!!

ふと思いたち、、今回、Google画像検索の結果をスクレイピングして、 画像データ(サムネイル)を取得して、それらをR/Keras用の4次元アレイデータに変換するプログラムを作成してみた。

実務としては、 rvestパッケージとかEBImageパッケージとかを使うことで実装した。

主な用途としては、GANとかで使うDL学習用の画像データを収集するのを想定している。

パッケージの準備

#パッケージの読み込み
library(magrittr)
library(EBImage)
library(rvest)

rvestの使い方の基本は、以下の記事を参照のこと。

skume.net

skume.net

画像の取得・変換を行う関数の定義

今回、GoogleImage2Array関数とdisplay.4dArray関数を以下の通り定義した。

GoogleImage2Array関数のデフォルトのパラメータでは、 64x64ピクセル(wh=64)の画像に変換する。 また、画像をローカルに保存しない(Save=FALSE)。

#Google画像検索で取得した画像サムネイルから4次元アレイデータを作る関数
GoogleImage2Array <- function(Query, wh=64, Save=FALSE){
url <- URLencode(paste0("https://www.google.co.jp/search?q=", Query, "&btnG=Google+Search&tbs=0&safe=off&tbm=isch"))  

imgsrc <- xml2::read_html(url) %>%
        rvest::html_nodes(xpath = '//img') %>% 
        rvest::html_attr('src') %>% 
        .[startsWith(., "https://")]

#アレイデータを格納する変数
Dat <- NULL

for(n in 1:length(imgsrc)){
#n <- 1
#URLを取り出す
imgsrc00 <- imgsrc[n]

#ローカルに保存する場合には、TRUEにする
if(Save){
download.file(imgsrc00, 
              paste0("Image_", formatC(n, width = 3, flag = "0"),".jpg"), mode = "wb")  
}

#画像読み込み
Img <- EBImage::readImage(imgsrc00, type="jpg")
#EBImage::display(Img, method="raster")

#リサイズ
ImgR <- EBImage::resize(Img, w = wh, h=wh)

#str(ImgR)
ImgRArray <- array(ImgR, dim=dim(ImgR))
#str(ImgRArray)
Dat[[n]] <- ImgRArray
}

#listからアレイに変換
Tensor <- base::aperm(base::simplify2array(Dat), c(4, 1, 2, 3))
#str(Tensor)

#出力
return(Tensor)
}

display.4dArray関数のQueryパラメータには、 GoogleImage2Arrayと同じ変数を入れる。 また、デフォルト設定で画像をローカル保存する(Save=TRUE)。

#アレイデータを可視化・画像保存する関数
#Queryには、GoogleImage2Arrayと同じ変数を入れる。画像をローカル保存する(Save=TRUE)。
display.4dArray <- function(x, Query=NULL, Save=TRUE){
par(mfrow=c(4,5), mar=rep(0, 4))
for(n in 1:dim(x)[1]){
  #n <- 1
  plot(t(as.raster(x[n,,,], max=max(x[n,,,]))))
}
if(!is.null(Query)){
if(Save){ quartz.save(paste0("Image_", Query, ".png"), type = "png")  }  
}
}

事例1: 「ペルシャ猫」をクエリとした画像検索の結果

#クエリの準備
Query <- "ペルシャ猫"

#検索&画像取得
images <- GoogleImage2Array(Query)

#アレイの情報
str(images)
#num [1:20, 1:64, 1:64, 1:3] 0.789 1 0.144 0.519 1 ...

#可視化
display.4dArray(images, Query=Query)

f:id:skume:20210921002823p:plain:w400

事例2: 「広末涼子」をクエリとした画像検索の結果

#クエリの準備
Query <- "広末涼子"

#検索&画像取得
images <- GoogleImage2Array(Query)

#アレイの情報
str(images)
#num [1:20, 1:64, 1:64, 1:3] 1 0.735 0.976 0.643 0.855 ...

#可視化
display.4dArray(images, Query=Query)

f:id:skume:20210921002827p:plain:w400

まとめ

さくっと、画像が取得できて、素晴らしい!

Google検索の仕様が変わらない限りは、当分の間、使い続けられそうである。

ただ現状、一度に、20枚の画像しか取得できないのは課題かも。

作成したスクリプト

gist.github.com

English page (Google translate)

参考資料

stackoverflow.com

stackoverflow.com

stackoverflow.com

qiita.com