画像データをWEB上から集めて、PC上に画像データとして保存する(Flickr API)

はじめに

これまで、MNISTやIirsといった用意されたデータを使って、CNNなどを勉強してきました. 今回から、自作のデータを使った画像分類を扱っていきたいと思います.いつ、どこで頓挫するかはわかりませんが、既に先人が残した様々な情報を駆使すれば私でもなんとかなるだろう思っています.

追記:1回のリクエストで500枚以上を指定するとエラーが生じますので、500枚以上を指定するときは少し工夫がいります.noteの方は更新しました.(端数とか少し無視しているので、私のやり方がベストではないと思います.)


やりたいこととしては、画像データをWEB上から集めて、それを機械学習で扱えるようにデータ化するということなのですが、 とりあえず今回はタイトルにある通り

『画像データをWEB上から集めて、PC上に画像データとして保存する』

ことを行いたいと思います.


いちいち自分のPCに持ってくる必要もないのですが、MNISTやIrisデータを扱うとき、画像を表示することもできるわけですが、少なくとも私はいまいちデータの実態が掴めていません.

windows一筋15年の私にとって、画像データといえば、マイピクチャフォルダに入っている写真データなわけで、そういった形でフォルダに入っているデータを扱えたら嬉しいわけです.

Flickr API

ウェブ上で画像を集める方法はいくつかあるようなのですが、今回は以下の記事を参考にFlickrを使った画像収集を行っていきます.無料でけっこうまとまった枚数の画像を入手できそうだというのが理由です.

ykubot.com

Flickr(フリッカー)は、写真の共有を目的としたコミュニティサイトです.非常に有難いことに、アップロードされている写真の情報が取得可能なAPIが公開されており今回はそれを利用します.APIの利用に必要なキKeyの取得などは、上記の記事を参照いただくとして、今回は画像を集めていくまでのスクリプトについてまとめます.

手順

主な手順としては、以下のようになります.

  • step 1
    • FlickrAPIを使って欲しい画像のタグ(dogとかcatとか)とURLを取得して、リスト化する
  • step 2
    • リストのURLに従い、urlretrieveを使ってダウンロードしていく

準備

APIキーの情報

先の記事を参考に自分で取得したkeyを入力してください

key = "XXXX取得したkeyを入力XXXXX"
secret = "XX取得したsecretkeyを入力XXX"

DLしたいデータをリスト形式で記述

別にコマンドプロンプト上で指定してもいいんですが、複数ある場合など何回も叩くのが面倒だったので、まとめてやるようにしました.参考にしたサイトでは1つずつやるようになっていると思います.今回は、ネコ科の動物を集めることにしました.

# ダウンロードしたい名前をclassesに記述
#--------- INPUT -------------------------------------------
classes = ["cheetah", "tiger", "leopard", "lynx", "lion",\
           "jaguar", "white tiger", "cat"]
#-----------------------------------------------------------

データをダウンロードするフォルダを作成

リストclassesの内容に従い、カレントディレクトリ(今作業しているフォルダ)の下に新しいディレクトリを作成する

nb_photo = len(classes)

for i in range(nb_photo):
    dir_name = classes[i] 
    dirpath = "./" + dir_name
    os.mkdir(dirpath)

Step1:FlickrAPIを使った必要な情報のリスト化

以下のコードで、必要な情報をFlickrから取得できます.
flickr.photos.search()のオプションで以下のことを指定できます.
per_pageが欲しいデータの枚数になります.当然、1000とかにするとそれなりに時間はかかります.

flickr = FlickrAPI(key, secret, format="parsed-json") #
response = flickr.photos.search(
    text = dir_name,
    per_page = 5,
    media = "photos",
    sort = "relevance", 
    safe_search = 1,
    extras = "url_q, licence" 
    )
    
photos = response["photos"] #

Step2:画像データのダウンロード

urlretrieve()を使って作成したリストに書かれた内容を元にデータをダウンロードしていきます.
引数は、以下となります.

  • url_q:画像データのあるURL
  • filepath:保存先フォルダ

また、たまに画像情報はあるのにurl_qがないのか『url_qがありません』というような内容のエラーが出て止まってしまうことがありましたので、その場合は無視して次の画像に進むようにしています.ですので指定した枚数に対して実際は8割~9割程度しか取得できないことも多いです.

for i, photo in enumerate(photos["photo"]):
    try:
        url_q = photo["url_q"]
        filepath = dirpath + "/" + photo["id"] + ".jpg"
        if os.path.exists(filepath): continue
        urlretrieve(url_q, filepath)
        time.sleep(wait_time)
    except:
        continue

以上の内容をまとめたコードはコチラに載せておきます


注意点とか

Flickrを使った場合、以上のように簡単に画像データを集めることができます.

注意点ですが、今回の使い方は学術研究、個人の趣味が目的の場合を想定しています.商用目的での使用する場合は、自分で調べていただくようお願いします.

また、指定するキーワード(タグ付け)が元のカテゴリに存在するものに限りますので、当然存在しないキーワードを指定しても画像を集めることはできません.

同様に、共有する人が少なそうなタグの場合、画像枚数が少ないです.
例えばFlickrで私の好きな【つば九郎】を検索した結果、198件しかありませんでした.


ですので、ニッチな画像を扱うにはFlickrは不向きかもしれません.

そういった場合、Google、BingのAPIなるものを使えばいいようなのですが、今回そこまで調べ切れていません.また、icrawlerなるライブラリを使えば、さらにそういったサイトからまとめてダウンロードできるようです.興味ある方は、以下のサイトなどを参考にしてみてください.

qiita.com sleepless-se.net

次回、『画像データから機械学習で使うデータへの変換』についてまとめる予定です.
誤り・不備がありましたらご指摘ください.よろしくお願いいたします