cucumber flesh

Rを中心としたデータ分析・統計解析らへんの話題をしていくだけ

Microsoft Cognitive Service Face APIにローカル上の画像を投げる

dichikaさんのMicrosoft Cognitive Serviceを使った記事APIに投げる画像はサーバ上にある必要がある、ということだが、リクエストボディのContent-Typeapplication/octet-streamを指定することでローカルファイルをサーバを経由せずに直接投げることができる。

こんな感じでやる。検証用の画像として、件のGlobal Tokyo.R集合写真を使う(メガネのおじさんたちがメガネのお姉さんになってくれやしないか… ) 。Ocp-Apim-Subscription-Keyに与えるAPIキーは各自が用意したものを使うこと。

library(purrr)
library(httr)
# 対象の画像のパスを指定する
x <- "~/Desktop/oretachino_globaltokyo_r.jpg"  # 幅5000pxに引き伸ばし
base.url <- "https://westus.api.cognitive.microsoft.com/face/v1.0/detect"
result <- httr::POST(base.url, body = upload_file(x), query = list(returnFaceAttributes = "age,gender,headPose,smile,facialHair,glasses,emotion", 
    language = "en"), httr::add_headers(.headers = c(`Content-Type` = "application/octet-stream", 
    `Ocp-Apim-Subscription-Key` = <api_key>))) %>% 
    httr::content()

先述の通り、Content-Typeの値をapplication/octet-streamに変更するのと、 readBin()を使ってローカルファイルをバイナリとして読み込ませる指定するという話。

ご指摘いただきました。ありがとうございます。

qiita.com

これらのアップロードにおいては,データはサーバにストリーミングで送信されます.データがRにチャンクとしてロードされ,リモートサーバに送られるのです.したがってメモリに収まらない大きなファイルもアップロードすることができます.

結果について確認しておくと、メガネ率は少し異なっている。画像のサイズが違うのだろうか。SwimmingGogglesつけてる人誰や…

result %>% map("faceAttributes") %>% map_chr("glasses") %>% 
    table()
## .
##       NoGlasses  ReadingGlasses SwimmingGoggles 
##              18              12               3

Enjoy!

leafletでベースタイルを表示させずにポリゴンだけを表示する方法と投影法を変更する方法

先日行われたGlobal Tokyo.Rにてleafletについて発表してきました。発表後、ドイツからの参加者 @henningsway から質問をもらいました。それがタイトルの内容です。ちょっと焦っていたので、いや多分無理、みたいな回答になってしまいましたが、落ち着いてやればできました。@henningsway にはツイッターで返答しておいたのですが、せっかくなのでブログ記事にまとめます。

まずは利用するパッケージを読み込んで、描画するデータを用意します。描画する地図データは国土交通省国土政策局「国土数値情報(行政区域データ 平成27年4月1日時点のデータ) http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03.html 」を使わせてもらいます。このデータは{jpndistrict}パッケージを使って呼び出します。

今回は「東京都」を描画することにします。jpndistrict::spdf_jpn_pref()都道府県コードを指定して地図データ(SpatialPolygonsDataFrame)を呼び出します。東京都は小笠原諸島伊豆大島を含んでいますが、表示の都合から、島嶼部については除外します。また、市区町村区分に応じて塗り分けを行うための処理を加えます。

library(leaflet)
library(dplyr)
pref <- jpndistrict::spdf_jpn_pref(code = 13) %>% 
    # 島嶼部の市区町村を除外する
mutate(city_code = as.character(city_code) %>% 
    as.numeric()) %>% filter(city_code < 
    13361) %>% # 市区町村に応じてラベルを割り振る
mutate(type = case_when(grepl("区$", .$city_name_full) ~ 
    "ward", grepl("市$", .$city_name_full) ~ 
    "city", grepl("町$", .$city_name_full) ~ 
    "country", grepl("村$", .$city_name_full) ~ 
    "village"))

次に、塗り分けのための関数を定義しておきます。

factpal <- colorFactor(colormap::colormap(nshades = n_distinct(pref$type), 
    colormap = colormap::colormaps$viridis), 
    pref$type)

では地図を描画します。

leaflet() %>% addPolygons(data = pref, fillColor = ~factpal(type), 
    weight = 1, fillOpacity = 0.7)

f:id:u_ribo:20170405004938p:plain

これだけ。いつも{leaflet}を使うときはaddTiles()を使ってベースタイルを表示させますが、逆にタイルなんていらないんだと考えればポリゴンだけを表示できます。とここまでで筆を置くのは物足りないので{leaflet}で投影法を変更した地図を描画する方法を紹介。

今度は{rnaturalearth}を利用してNatural Earthが提供する地図データを使います。

library(rnaturalearth)

m.world <- ne_countries(returnclass = "sf")
crs.molvidde <- leafletCRS(
  crsClass = "L.Proj.CRS", 
  code = "ESRI:53009",
  # モルワイデ図法
  proj4def = "+proj=moll +lon_0=0 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs",
  resolutions = c(65536, 32768, 16384, 8192, 4096, 2048))

popcolor <- colorNumeric(colormap::colormaps$viridis, domain = m.world$pop_est)

leaflet(options = leafletOptions(
    maxZoom = 5, crs = crs.molvidde, attributionControl = FALSE)) %>% 
  addGraticule(style = list(color = "#999", weight = 0.5, opacity = 1)) %>% 
  addGraticule(sphere = TRUE, style= list(color = "#777", weight = 1, opacity = 0.25)) %>% 
  addPolygons(data = m.world,
              weight = 1,
              fillOpacity = 0.7,
              fillColor = ~popcolor(pop_est)
              )

f:id:u_ribo:20170405005606p:plain

m.asia <- ne_countries(continent = "asia", 
    returnclass = "sf")
leaflet(options = leafletOptions(crs = leafletCRS(crsClass = "L.Proj.CRS", 
    code = "EPSG:102025", proj4def = "+proj=aea +lat_1=25 +lat_2=60 +lat_0=36 +lon_0=139 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs", 
    resolutions = c(65536, 32768, 16384, 
        8192, 4096, 2048)), attributionControl = TRUE)) %>% 
    addPolygons(data = m.asia)

f:id:u_ribo:20170405005727p:plain

Enjoy!

leafletで描画した地図を画像ファイルとして保存する

お手軽に地図データを表示するために{leaflet}を頻繁に利用しているが、出力した地図を画像に保存するにはOSのスクリーンショット機能やアプリケーションを使う必要があって面倒だった。

調べてみると{mapview}パッケージに{leaflet}レンダリング結果を保存できる関数があるそうなのでメモ。

以下のコードでleaflet()の実行結果を画像(あるいはHTML)として保存できる。

library(magrittr)
library(leaflet)
library(mapview)
m <- leaflet() %>% addTiles() %>% addProviderTiles("Stamen.Watercolor") %>% 
    setView(lng = 135, lat = 38, zoom = 3)
mapview::mapshot(m, file = paste0(getwd(), 
    "/map.png"))

当然ながら動かした状態を保存することはできないので、描画される領域はsetView()やらfitBounds()で調整し、ラベルやポップアップの表示が必要であればあらかじめ表示するようにしておく。

f:id:u_ribo:20170328202001p:plain

Enjoy!