北緯35度付近での0.000001度(1μ°)は何メートルだろうか

緯度経度を Geocoding などの Web サービスで求めると、0.000001度(小数点以下6桁)精度で値を返してくれます*1。0.000001度というのは1マイクロ度(1μ°)。さて、この一番下位の桁が1ずれる(1μ°ずれる)と、距離にしてどれくらいずれるのでしょうか?という素朴な疑問が生じました。
@riocampos が普段生活しているのは北緯35度(島根県浜田市から千葉県館山市を結ぶ線上)付近。なのでこの辺りでの1マイクロ度当たりの距離を求めれば良いのです。

Webサービスに頼る

国土地理院測量計算(距離と方位角の計算)という Web サービスを提供してくれています、ありがたいですね。ここで1マイクロ度ずらした緯度経度を入力して、距離を算出させてみます。

結論:1マイクロ度で10cmぐらい

北緯35度東経135度を基準点として算出させました。

緯度経度の差 距離
緯度1μ° 0.111m
緯度10μ° 1.109m
緯度100μ° 11.094m
経度1μ° 0.091m
経度10μ° 0.913m
経度100μ° 9.129m

つまり緯度も経度も、1マイクロ度で10cm、10マイクロ度で1mのずれになる、ってことでした。
よって、Web サービスで求めた緯度経度で、一番下位の桁(小数点以下6桁)ぐらいずれても大したことないのですね。

ちなみに原理原則から緯度1マイクロ度を算出してみると

1m は地球の1周の長さを基準にして決められた、ということをご存じの方もおられるでしょう。より正しく言えば「子午線に沿った地球1/4周(赤道(北緯/南緯0度)から極点(北緯/南緯90度)まで)の長さを『1万km』となるように1mを決めた」わけです*2。ということは、1万kmが緯度の90度に相当するわけですね。
よって1度は1万km/90≒111km、すなわち111000m、さらに書き換えると0.111×106mぐらいになります。
1マイクロ度というのは1×10-6度です。よって距離としては(0.111×106×1×10-6)m、階乗部分が打ち消しあいますので0.111mになります。上で求めた値とほぼ合致しますね!
とはいえ上の計算は地球の子午線が全くの円形であるとして計算したことになります。実際の子午線は楕円なので、少しずれます。とはいえそこまで細かい精度は必要ありませんから、特に問題ないでしょう。

*1:なお Google Maps のURLでは小数点以下7桁になってますが、精度面で意味あるかといわれると無いですね。なにせ 1cm 精度になってしまうので。

*2:今の1mの定義は違いますよ

GPS機能の無いデジカメで撮った写真ファイルのEXIF情報に位置情報を追加する安価なやり方(Mac & CUIツール版)

普段の写真は iPhone 6s で満足なのですが、ときどき優秀な望遠ズームとマクロが欲しい @riocampos です。
今はずっと前に妻が買った

を使っています。色が微かな緑色なのと、コケ写真を撮影する為に 1cm マクロを目的に選んだこともあり、我が家では「もすもす」との愛称で呼んでいますw*1

デジカメにGPS機能なんてほとんど無い時代でしたね

高級機種には GPS 機能が載っていたのですが、さすがにコンパクトデジカメにまでは GPS が載っていない時代。 iPhone で撮影すると勝手に位置情報が加わるのに「もすもす」で撮影すると位置情報が分からない。それを写真.appで同じように扱うと、すこし辛い。位置検索できないし。

EXIF情報を後から追加するソフトもあるけどね

以前、iPhone でのトラックログMac で見るときには myTracks - The GPS solution for iOS and macOS というアプリを使っていました。この myTracks を使うと写真ファイルにも位置情報を追加出来たのです。ただし。「以前」というのは、このアプリがまだ無料だった時代のこと。今は有料アプリになりました。まあ有料でも良いのだけど、ただ機能的に $17.99 は高いのではと感じるのですよ。セコいのだけど。
Windows ユーザーであれば カシミール3D / 風景CGと地図とGPSのページ があるので何も考える必要はありませんな。しかも位置情報を埋め込むための デジカメプラグイン もありますので、この記事自体が要らないw

素晴らしき神ツールExifTool

ということで何らかの優秀な CUI ツールが存在しないかなーと探したところ、当然のように存在していました。
ExifTool by Phil Harvey
というか、世の中の EXIF が扱えるほとんどの GUI アプリは ExifTool を使っている、ような気もします*2
しかも超優秀なツールなので、経度緯度の直接設定でも、トラックログのデータから位置補完しての設定でも、いろいろと位置情報を設定することが可能。そして…無料。素晴らしい。神ツールと呼ぶに相応しい。

前振りが長くなりました

ということで ExifTool を使って位置情報を追加する方法を(自分用に)記録しておきます。

ExifToolをインストールする

上記サイトからインストールすれば良いです。ただし Homebrew を使っているのであれば

$ brew install exiftool

するのがラクでいいです。しかも ExifTool は更新が頻繁に行われるので、メンテナンス性の面からも Homebrew でのインストールをオススメします。

緯度経度での位置指定

まずは、写真に埋め込みたい位置の緯度経度を求めます。

などの Web サービスを使うのが便利です。
もしくはGoogle Mapsでも若干の手間をかければ求められます。

場所の座標を調べる
  1. パソコンで Google マップを開きます。Google マップをライトモードで使用中で、画面下部に稲妻のアイコンが表示されている場合は、場所の座標を表示できません。
  2. 地図上の目的の場所を右クリックします。
  3. [この場所について] を選択します。
  4. 画面下部のカードに座標が表示されます。

緯度と経度の確認、入力 - パソコン - マップ ヘルプ

例えば大阪城

大阪城 座標(WGS84) 緯度: 34.687315 経度: 135.526201

Lat Long
(34.687315, 135.526201)
GPS Coordinates
34° 41' 14.334'' N
135° 31' 34.3236'' E
Latitude and Longitude Finder on Map Get Coordinates

二つのサービスとも同じく「緯度: 34.687315 経度: 135.526201」になりました。
ではこれを写真一枚、もしくは複数の写真に設定します。念のために大元の写真ファイルではなく、コピーした写真ファイルを使いましょう。
今回は写真10ファイルが入ったディレクトリを指定しています。写真一枚なのであれば、ファイルパスを直接指定すれば良いです。

$ exiftool -P -overwrite_original -gpslatitude=34.687315 -gpslongitude=135.526201 /Users/riocampos/Pictures/100RICOH/
    1 directories scanned
   10 image files updated

さて。ExifTool のオプションについて順番に簡単に説明します。

-P-preserve
位置情報を埋め込んだ処理後の写真ファイルの変更日を元の写真ファイルと同じままにします。このオプションを指定しないと、処理後の写真ファイルの変更日が ExifTool のコマンド実行日時になります。
-overwrite_original
位置情報を埋め込んだ処理後の写真ファイルで、元の写真ファイルに対して上書きします。今回は上記したようにコピーした写真ファイルを使っているのでこのオプションを使っています。
なお、上書きしない場合には処理後の写真ファイルが元ファイルと同じフォルダに書き出されます。
処理後の写真ファイルを他のディレクトリに書き出す場合は -o-out)オプションを指定して、その引数に出力先ディレクトリを指定してください(ディレクトリなので末尾の/を忘れないように)。

-gpslatitude=XX.XXXX (または -exif:gpslatitude=XX.XXXX
-gpslongitude=YYY.YYYY (または -exif:gpslongitude=YYY.YYYY
緯度経度の指定。オプション名を読めば分かりますよね*3
おまけとして

-v
verbose オプションです。以下のような感じで進行状況を表示してくれます。たくさんのファイルを変更するときには作業してるのかどうなのか気になるので、このオプションを付けておくと良いでしょう。
======== /Users/riocampos/Pictures/100RICOH/RIMG0001.JPG
Rewriting /Users/riocampos/Pictures/100RICOH/RIMG0001.JPG...
  Editing tags in: APP0 APP1 GPS IFD0 JFIF MIE-GPS XMP 
JPEG APP1 (xxxxx bytes):
  Rewriting IFD0
  Rewriting ExifIFD
  Rewriting MakerNoteRicoh
  Rewriting ImageInfo
  Rewriting RicohSubdir
  Rewriting FaceInfo
  Rewriting FirmwareInfo
  Rewriting SerialInfo
  Rewriting InteropIFD
  Creating GPS
  Rewriting IFD1
JPEG APP2 (xxx bytes):
JPEG DQT (xxx bytes):
JPEG SOF0:
JPEG DHT (xxx bytes):
JPEG SOS

そして ExifTool はコマンドの末尾に処理目的のファイルパスを指定します。

追記:Error: [minor] Bad format (512) for MakerNotes entry 0 などという MakerNotes エラーが出て位置情報が追加出来ない場合には

[minor] と書いてありますし、焦らず騒がずマイナーエラーを無視する -m オプションで対応しましょう*4
詳細は 15. "I get MakerNote warnings or errors when reading or writing information"|ExifTool FAQ をお読みください。

本当はトラックログデータのことを書くつもりだったが疲れたので一旦ここまで

例示するとこんな感じ。この場合はkmlファイルですけど、gpxファイルでも大丈夫。

$ exiftool -P -overwrite_original -geotag /Users/riocampos/Downloads/history-2018-08-07.kml /Users/riocampos/Downloads/100RICOH

そのうちに ExifTool のオプションについての解説記事が書ければいいなあ。高機能でしかも無料なので、みんなで使いましょうね。

2021/5/25 追記

まだ GPS なしコンパクトデジカメで撮影したものに exiftool で GPS 情報を付加しております。その際には SD カードを Mac に接続してオリジナル画像で更新し、 iPhone にSD カードリーダを繋いで読み込ませています。その際に使うリーダは純正のこちら ↓

Apple Lightning - SDカードカメラリーダー

Apple Lightning - SDカードカメラリーダー

  • 発売日: 2015/12/10
  • メディア: Wireless Phone Accessory
で、今日はいつも通りにその作業をした後に、ちょっと Mac へ書き出ししたのですが、コンパクトデジカメで撮影した画像の日付などが iPhone への読み込みをした時刻になってしまっていました。これはうれしくない。でも exif データには撮影時刻も入っているわけで、その情報を使えばファイルの日時も簡単に修正出来ました。

$ exiftool "-FileModifyDate<DateTimeOriginal" *.JPG

やはりありがたいツールです> exiftool 。
(参考:exiftoolでファイルの変更日時を写真の撮影日にする方法 - Qiita

2021/5/25 追記2

兄から送られてきた写真が回転されずに保存されていたのだけど、きっと exif データの回転指定だけで何とかなるだろうと思って検索したところ、やはり exiftool で解決出来ました。

$ exiftool -P -overwrite_original -Orientation=6 -n RIMG0001.JPG # 6:時計回り90度
$ exiftool -P -overwrite_original -Orientation=8 -n RIMG0002.JPG # 8:反時計回り90度

参考サイト:

おまけ

クセのあるデジカメが好きなので、現時点だとこのあたりがいいなあ*5

*1:ああもう2011年の機種なんだなあ、かなり古いよなあ…

*2:本当かどうか分からんけど

*3:なお緯度経度は北緯と東経が正の値。日本国内であれば両方とも常に正の値。南半球であれば緯度が負の値、アメリカ大陸とか西半球であれば経度が負の値。上記 Web サービスを使えば出力値をそのまま使えば良いのでラクチンです。

*4:当方では、カメラから移動させただけのはずなのに、なぜか撮影時刻と違う変更時刻になっていたファイルが居て、そいつがこのエラーを吐きました。

*5:DSC-RX100M6やM7 は絶対買えないだろうがw

gogakuondemand.rbをv1804_1に更新

すみません、今回はデバッグのための更新です。NHKのせいではありません…。

それから、基礎英語0のストリーミングサイトが他の番組と若干異なっております。そのため、もしかすると5月に再度更新するかもしれません。

と書いておりましたが、5月に変わったら予期していた仕掛けが上手く行かず暴発しましたorz

ということで、またいつものところ
NHK語学講座のラジオ番組ストリーミングを取得するRubyスクリプトgogakuondemand.rb(v1804_1 2018/5/5更新版) - 別館 子子子子子子(ねこのここねこ)をご覧ください。
ダウンロードもそこから行えます。
よろしくお願いします。

gogakuondemand.rbをv1804に更新

NHK大好きな[twitter:@riocampos]です。
毎度おなじみ gogakuondemand.rb を更新しました。
今回は年度変更に伴う番組変更への対応を行いました。具体的には

  • 短期集中!3か月英会話 削除
  • 基礎英語0 追加
  • 遠山顕の英会話楽習 追加

以上の3番組への対応です。
また、ダウンロード範囲を同一年度に限定しました。特に

の為の変更です。ボキャブライダーは未だに2017年度のファイルもアップされているのでダウンロード出来ますが、いちいち全ファイルの確認を行う必要も無いと思いましたのでそのように変更しました。
なお、pref.rb ファイルでの "school_year" 設定変更で2017年度分もダウンロード可能ですが、ボキャブライダー以外の番組に対してもダウンロード対象年度が限定されます。必要なときにだけ変更してください。
それから、基礎英語0のストリーミングサイトが他の番組と若干異なっております。そのため、もしかすると5月に再度更新するかもしれません。

またいつものところ
NHK語学講座のラジオ番組ストリーミングを取得するRubyスクリプトgogakuondemand.rb(v1804 2018/4/9更新版) - 別館 子子子子子子(ねこのここねこ)
をご覧ください。
ダウンロードもそこから行えます。
よろしくお願いします。

WatirでHeadless Chromeを使うまでのメモ

サーバ的環境から JavaScript が必要なブラウザアクセスする場合はいままでずっと PhantomJS を使ってきたわけですが、残念ながら PhantomJS は2017年6月ごろで開発を終了したそうです*1
ということで遅まきながら Headless Chrome を使ってみることにしましたのでメモ書きします。

更新すべきもの

  • chromedriver

これが一番のネックでした。Chrome に内蔵されていないと思ってなかったので、古いバージョンのまま使っていました。その際のエラーはこんな感じ。

browser = Watir::Browser.new(:chrome, headless: true)                                                       
Selenium::WebDriver::Error::UnknownError: unknown error: unrecognized Chrome version: HeadlessChrome/64.0.3282.186
  (Driver info: chromedriver=2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9),platform=Mac OS X 10.12.6 x86_64)
from /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.9.0/lib/selenium/webdriver/remote/response.rb:69:in `assert_ok'

chromedriver=2.27 ってちゃんと出てますよね。気付けよ>俺。
で。chromedriver の更新を今後も継続的に行うため、今回は Homebrew でインストールすることにしました。現時点のバージョンは2.35。

$ brew info chromedriver
chromedriver: stable 2.35
Tool for automated testing of webapps across many browsers
https://sites.google.com/a/chromium.org/chromedriver/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/chromedriver.rb
==> Caveats
To have launchd start chromedriver now and restart at login:
  brew services start chromedriver
Or, if you don't want/need a background service you can just run:
  chromedriver
$ brew install chromedriver
==> Downloading https://chromedriver.storage.googleapis.com/2.35/chromedriver_mac64.zip
######################################################################## 100.0%
Error: The `brew link` step did not complete successfully <==ここでエラー出ていることに気付こう…
The formula built, but is not symlinked into /usr/local
Could not symlink bin/chromedriver
Target /usr/local/bin/chromedriver
already exists. You may want to remove it:
  rm '/usr/local/bin/chromedriver'

To force the link and overwrite all conflicting files:
  brew link --overwrite chromedriver

To list all files that would be deleted:
  brew link --overwrite --dry-run chromedriver

Possible conflicting files are:
/usr/local/bin/chromedriver
==> Caveats
To have launchd start chromedriver now and restart at login:
  brew services start chromedriver
Or, if you don't want/need a background service you can just run:
  chromedriver
==> Summary
&#127866;  /usr/local/Cellar/chromedriver/2.35: 4 files, 11.3MB, built in 16 seconds

インストールは終わったので確認。

$ which chromedriver
/usr/local/bin/chromedriver
$ chromedriver
Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 9515 <==バージョンが以前のものになっていることに気付こうよ…
Only local connections are allowed.
^C

ということで古いものを削除。

$ rm '/usr/local/bin/chromedriver'
$ brew link chromedriver
Linking /usr/local/Cellar/chromedriver/2.35... 1 symlinks created

現時点のバージョンは3.9.0。ちなみに3.6.0から「PhantomJS は deprecated」と出るようになりました。

$ gem update selenium-webdriver
Updating installed gems
Updating selenium-webdriver
Fetching: selenium-webdriver-3.9.0.gem (100%)
Successfully installed selenium-webdriver-3.9.0
Gems updated: selenium-webdriver

現時点のバージョンは6.10.3。Headless Chrome が使えるようになったのは6.6からだそうです。
インストールログを消しちゃいましたが、まあ selenium-webdriver と同様に gem update しちゃえばいいわけで。

Headless Chrome実行時の注意

Headless Chrome を先に起動した状態から Chrome も起動しようとしたのですが、起動しませんでした。どうやら先に画面ありのふつうの Chrome を起動しておかないとダメみたいですね。まあ普段は Mac の起動と同時に Chrome も立ち上げますから問題無いでしょう。

実行してみる

$ pry
[1] pry(main)> require 'watir'                                                                                             
=> true
[2] pry(main)> browser = Watir::Browser.new(:chrome, headless: true)                                                       
=> #<Watir::Browser:0x..fbfcb7aab4783eb70 url="data:," title="">
[3] pry(main)> browser.goto "www.yahoo.co.jp"                                                                              
=> "http://www.yahoo.co.jp"
[4] pry(main)> browser.screenshot.save("yahoo.jpg")                                                                       
2018-03-01 16:07:06 WARN Selenium name used for saved screenshot does not match file type. It should end with .png extension
=> #<File:yahoo.jpg (closed)>

スクリーンショットpng じゃないと怒られるようです(以前はそんなことなかったのに。
ではこの記事のサイトを撮影しましょう。

[5] pry(main)> browser.goto('http://d.hatena.ne.jp/riocampos+tech/20180301/watir_with_headless_chrome')                    
=> "http://d.hatena.ne.jp/riocampos+tech/20180301/watir_with_headless_chrome"
[6] pry(main)> browser.screenshot.save('htd.png')                                                                          
=> #<File:htd.png (closed)>

こんなスクリーンショットが撮れました。

*1:とはいえ最新の PhantomJS は http://phantomjs.org/release-2.1.3.html を見ると2018年1月リリースなんだよね。

Google検索で日付範囲指定したい場合(2016年以降)

2016年より前だと、Google検索窓の検索文字列に「daterange:YYYY-MM-DD..YYYY-MM-DD」を追記すれば良かったようなのですが、最近は使えなくなってしまいました。
いまは、例えば2016/1/1から2017/2/21までを検索したい場合だと検索URLに

&tbs=cdr%3A1%2Ccd_min%3A1%2F1%2F2016%2Ccd_max%3A2%2F21%2F2018

を追記するようにします。
で、cdr以降は何かというと

encodeURIComponent("cdr:1,cd_min:1/1/2016,cd_max:2/21/2018")

の結果なのです。日付は米国式にMM/DD/YYYYと書かなきゃいけない、ので面倒です。

これを追記するための bookmarklet を書きたいのですが、面倒になって書いてません。
だれか書いてくださいw

2019/2/19追記:書いてる人が居た。しかもこのブログ記事よりもずーっと前の記事でしたw

でもこの記事のころはまだ YYYY/MM/DD だったようです。
この bookmarklet を更新した方がいらっしゃいます。

ということで後者を使いましょう。

tbsって何だ

検索結果の日付範囲指定やソート順などを指定する要素みたいです。

  • tbs=sbd:1 →(0:古い順、1:新しい順)
  • tbs=qdr:h →(1時間以内
  • tbs=qdr:h24 →(24時間以内
  • tbs=qdr:d →(1日以内
  • tbs=qdr:w →(1週間以内
  • tbs=qdr:m →(1ヶ月以内
  • tbs=qdr:m6 →(6ヶ月以内
  • tbs=qdr:y →(1年以内更新
  • tbs=qdr:y2 →(2年以内

google検索を最新順にソートする方法 - そこに落ちてた帳面

heroku-buildpack-imagemagickの使い方

Twitter bot に画像処理を加えたいと思って Ruby MiniMagick gem を使いました。
で、デプロイしたあとに気付きました。
あ、ImageMagick を使えるように設定してない!
大急ぎでやり方を探して処理しました。

heroku-buildpack-imagemagick

とはいえ簡単な処理なのです。 heroku に buildpack を追加するだけ。

ImageMagick

ImageMagickのビルドパックは公式からは提供されていませんが、カスタムビルドパックを作ってる人がいるのでこれを利用します。

$ heroku buildpacks:add https://github.com/ello/heroku-buildpack-imagemagick

これでImageMagickのカスタムビルドパックの追加が完了です。
HerokuでImageMagickのconvertができるまで - Qiita

これですね。
ello/heroku-buildpack-imagemagick

実行

$ heroku buildpacks:add https://github.com/ello/heroku-buildpack-imagemagick
Buildpack added. Next release on twitter-bot will use:
  1. heroku/ruby
  2. https://github.com/ello/heroku-buildpack-imagemagick
Run git push heroku master to create a new release using these buildpacks.

空コミットする必要があります。

$ git commit -m "add heroku-buildpack-imagemagick" --allow-empty
[master 69186ad] add heroku-buildpack-imagemagick

ではデプロイしましょう。

$ git push heroku master
Counting objects: 1, done.
Writing objects: 100% (1/1), 196 bytes | 196.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Ruby app detected
remote: -----> Compiling Ruby
 :
remote: -----> Detecting rake tasks
remote: 
remote: -----> ImageMagick app detected
remote: -----> Install ImageMagick
remote: -----> Downloading ImageMagick from http://www.imagemagick.org/download/releases/ImageMagick-6.9.5-10.tar.xz
remote: --2018-02-15 13:47:21--  http://www.imagemagick.org/download/releases/ImageMagick-6.9.5-10.tar.xz
remote: Resolving www.imagemagick.org (www.imagemagick.org)... 198.72.81.86
remote: Connecting to www.imagemagick.org (www.imagemagick.org)|198.72.81.86|:80... connected.
remote: HTTP request sent, awaiting response... 200 OK
remote: Length: 8794440 (8.4M) [application/x-xz]
remote: Saving to: ‘/tmp/build_e7e5db58f15dc697460ae578ff813215/ImageMagick-6.9.5-10.tar.xz’
 :
remote: -----> Extracting ImageMagick from /tmp/build_e7e5db58f15dc697460ae578ff813215/ImageMagick-6.9.5-10.tar.xz
 :
remote: -----> Building ImageMagick
 :
remote: -----> Caching ImageMagick installation
remote: -----> Writing policy file
remote: -----> Updating environment variables
remote: -----> Discovering process types
remote:        Procfile declares types -> bot
remote: 
remote: -----> Compressing...
remote:        Done: 56.2M
remote: -----> Launching...
remote:        Released v31
remote:        https://twitter-bot.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/twitter-bot.git
   75f8ab8..69186ad  master -> master
[https://gist.github.com/riocampos/2e758f3d359796b93ff19356d6f76f08:title=heroku log after `heroku buildpacks:add https://github.com/ello/heroku-buildpack-imagemagick`]

ImageMagick のビルドに6分ぐらいかかった。

動くか確認

先ほどの Qiita 記事に従って、動くかどうかを確認してみましょう。

$ heroku run magick -version
Running magick -version on ⬢ colbase-bot... up, run.2716 (Free)
bash: magick: command not found

あれ?
でも ImageMagick ってだいたいは convert コマンドを使うよね?

$ heroku run convert -version
Running convert -version on &#11042; colbase-bot... up, run.2202 (Free)
Version: ImageMagick 6.9.5-10 Q16 x86_64 2018-02-15 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2016 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC OpenMP 
Delegates (built-in): bzlib djvu fontconfig freetype jbig jng jpeg lcms lqr lzma openexr png tiff wmf x xml zlib

動いた動いた^_^