マレーシア航空旅客機の衛星写真を画像解析
マレーシア航空のいろんな話題が飛び交っている中、Twitterで「【助けて】全世界のインターネットユーザーに協力を呼びかけ! この写真から「消息を絶ったマレーシア航空の旅客機」を見つけてください」という記事を見つけました。
衛星写真の画像が大量にあるので、人海戦術で破片を見つけよう、という趣旨です。私は分析屋なので、データサイエンスを使って手助けできないか?と思い、少し分析してみました。何かの一助になればと思い、ブログで公開します。
データサイエンスを利用するには、まずデータが必要です。衛星画像はこのサイトにあります。
そのサイトから、まずは特徴的な画像を拾ってきて、分析してみます。サイトを見てみると、画像はだいたい3つのパターンに分かれているようでした。
- 雲の画像
- 海の画像
- 何かの物体の画像
3つ目の”何かの物体”を画像から判定できれば、それが旅客機かもしれません。分析のロジックを作るために、ある船が含まれる画像を使って分析してみました。その画像が次のものです。サイト上ではこのページ(23975番)の画像です。
衛星画像をいくつか適当に眺めて、たまたま見つけたものです。まずは特徴的なこの画像を使って、分析ロジックを検討します。船とヘリポートが写っており、これを画像解析によって見つけられるか試します(画像データのダウンロードはできなかったので、Web画面のスクリーンショットを保存しました)。
分析には、いつものように統計解析ソフトであるRを利用します。Rでの画像処理に関しては、@wdkzさんの「Rでウォーリーを探してみた」の記事が大変参考になりました。この場を借りてお礼申し上げます。
まず、飛行機が写っているとしたら画像では白っぽくなるだろうと思い、画像から”白っぽい物体”を抽出するロジックを考えました。いろいろ試行錯誤しましたが、結果的に、次のような順で行うことで”白っぽい物体”を抽出できました。
1.白っぽい部分以外を1色に塗りつぶす
2.白っぽい部分も1色にする
3.色を少しぼやけさせる
4.ぼやけた部分をくっきりさせる
5.ノイズを除去する
最終的に出来た画像が、5の処理で行ったものです。赤く協調されているものが”白っぽいもの”です。もともとあった船とヘリポートがしっかりと認識されています。ただ、他にもいくつか赤い点があります。もとの画像をみると、恐らく海の波か何かなんじゃないかと思いますが、ちょっと分かりません。ただ、1つ目の画像処理の時点で、何か浮き出てますね。。何だろ、、、もしかしたら目的のものの一部?
これで”白っぽいものを認識する”ロジックはできたはずなので、確認のために他の画像にも当てはめてみます。先ほどの海域の左にある、雲の画像に当てはめてみたものが、次の結果です。
もとの画像
解析後の画像
2枚目が解析後の画像ですが、雲が1つの物体と認識されてないので明らかにおかしいです。多分、判定ロジックのどこかがおかしく、まだ改良しなくてはならなさそうです。これがうまくいったら次は、「雲かどうか」も何かしらのロジックで判別しなくてはならないですね。
とりあえず今思い付く方法はこれくらいです。これらをまとめると、次の3点です。
- 画像の白色判定はうまくいったので、飛行機を見つけるときの補助ができる(人が目で見る分には、処理1か2だけで良いかもしれない)
- 【課題】雲を見分ける必要がある(雲が無い衛星写真があればベスト)
- 【課題】サイトから画像が全部ダウンロードできないので、自動で取得してくる必要がある
今できるのはこれくらいですが、改良すればもっと実用的になるかもしれません。何かコメントがあればTwitterの方でどうぞ。全画像が手に入れば、ビッグデータ解析になります。
なるべく早く事案が解決することを願っています。
以下、Rのコードです。ご参考下さい。
# ImageMagickなどのインストール(ImageMagickは結局使ってない) library(installr) install.ImageMagick() install.packages(c("abline", "biOps")) source("http://www.bioconductor.org/biocLite.R") biocLite("EBImage") source("http://rimagebook.googlecode.com/svn/installRImageBook.R") installRImageBook() require(EBImage) require(biOps) require(RImageBook) # setwd直下に、画像番号をファイル名にしたキャプチャpng画像を置いておく # setwd直下に画像の番号を付けたフォルダを作る必要がある WhiteExtract <- function(number){ MalayAir <- readImage(file=paste("MalayAir", number, ".png", sep="")) # display(MalayAir) # gtkとImageMagickの設定が難しい。writeImageで代用する。 # 白色抽出 writeImage(MalayAir, paste(number, "/MalayAirTest0.png", sep="")) MalayAir.white <- MalayAir MalayAir.white[MalayAir.white > 0.1] <- 1 writeImage(MalayAir.white, paste(number, "/MalayAirTest1.png", sep="")) MalayAir.white2 <- thresh(MalayAir.white, w=50, h=50, offset=0.1) writeImage(MalayAir.white2, paste(number, "/MalayAirTest2.png", sep="")) MalayAir.white3 <- gblur(MalayAir.white2, sigma=1) writeImage(MalayAir.white3, paste(number, "/MalayAirTest3.png", sep="")) MalayAir.white4 <- (MalayAir.white3 > 0.1) writeImage(MalayAir.white4, paste(number, "/MalayAirTest4.png", sep="")) kern <- makeBrush(7, shape="diamond") MalayAir.white5 <- closing(opening(MalayAir.white4, kern), kern) writeImage(MalayAir.white5, paste(number, "/MalayAirTest5.png", sep="")) writeImage(MalayAir.white5, paste("MalayAir", number, "_判定後.png", sep="")) MalayAir.white5.label <- bwlabel(MalayAir.white5) print(max(MalayAir.white5.label)) } WhiteExtract(21387) WhiteExtract(24889)