ochalog

Ruby と MediaWiki が好きな電子・情報系の学生のブログ。

研究分野への興味の喪失

夏休みに入り、興味を持ったソーシャルデータの分析の研究室の先生とお会いしてお話を伺った。その後、提出しなければならない修士課程の研究計画書を書くために調査をしていたが、調べているうちに興味がなくなってきた。

先生との面談の際には、ここ何年かの実習で災害についての情報を扱う機会が何回かあったこともあり、ソーシャルメディアへの投稿から災害についての情報を検出し、物理センサを補完するような仕組みを作りたいと伝えた。特にこの時期に多く起こる豪雨災害を対象にしようと考えていた。そのまま話が進んだので、研究計画書を書くためにさらに調査を進めたが、調べていくと成功する見込みが少ないと感じられるようになった。

例えば代表的なソーシャルデータであるツイートを収集するボットを作るのは今からすぐにできると思う。作っていたIRCボットのcre-ne-jp/rgrbTwitter gemを使っている経験があるから、APIについて調べて利用し、得られたデータを整形すれば良いだろう。自然言語処理を利用した必要なデータの抽出も、頑張って勉強しながらなんとかできるようになりそうだとは思った。その後の他データとの比較は、時刻や位置情報に注目しながら地道にやっていくことになるだろう。

問題はテーマに当てはまる投稿がそもそもあるのかどうか。調べていくうちに、これが心配になってきた。

最近の関連研究はほとんどない。東日本大震災の直後は結構多いように見えたが、最近は下火になっているようだった。これは興味を持っている人が少ないか、やってみたが成果がほとんどないということを示しているように感じられた。

それなりに上手くいっていそうな例は、早稲田大の「人間科学研究」に載っていた、服部による「位置情報付きツィートから事象 (自然現象・異常気象)・災害を可視化する手法の開発」だけだった。ただ、修士論文の要旨なので詳細は分からなかった。

他に、災害情報No. 14(2016)に掲載された潮崎・牛山による「豪雨時における災害危険度の高まりを推定するための電話通報数の活用について」の参考文献に載っていた、影澤らによる「Twitterを用いたセンシングシステムの提案と考察」(「マルチメディア、分散協調とモバイルシンポジウム2014論文集」に掲載)が気になったが、人が多い新宿でも降雨初期のツイートが数件というのを見て愕然とした。一応降雨を検出できたことになっているが、1時間に少なくとも数千件のツイートを収集しているのに対象ツイートがこの件数になるというのでは、多少のシステムの改良ではどうしようもないほど関連するツイートの絶対数が少ないということではないだろうか。

さらに同じ日に読んだ2015年関東・東北豪雨災害土木学会・地盤工学会合同調査団関東グループによる調査報告書を読んでより悲観的になった。p. 135の「避難情報の入手手段」の図の「SNSTwitter、LINE、Facebook等)」の割合が0.4%(N = 516)というのは、要するに、そんな大災害のときに呑気にSNSに興じているような人はほとんどいないことを示していると思われた。一応「入手手段」なので投稿数もそれくらい少ないとは限らないが、平時に近い上の新宿の場合と比べれば、非常時には普通は減るだろう。また、別の豪雨災害の2014年広島豪雨は深夜に酷い被害が出たことから、そのような場合もSNSへの投稿はほぼなくなるだろうと推測した。

というわけで、ここ数日集中して調べた限りでは、豪雨災害を研究対象とすると投稿のサンプルが集められずに挫折する可能性が高いという予想になった。そのため、自分はこのテーマに賭けようという気持ちになれなかった。

他には研究室の本流らしい観光に関連したデータの抽出が流行っているようだったが、利用者に合わせた推薦の手法の提案ばかりで、差別化が難しいと感じた。あまり興味が持てなかったこともあり、今は独自のテーマが浮かびそうにない。


当初は個々の技術がおもしろそうだと思っていたが、適用できそうな範囲の狭さを知り、ソーシャルデータの分析への興味がなくなってきた。代わりの案はまだ浮かんでいない。

gstreamermmでGStreamerのチュートリアル1

卒研で使うThe Imaging Source社の産業用カメラをLinuxで制御する1ためにマルチメディアフレームワークGStreamerを使うことになりそうなので、その練習をしている。

卒研ではOpenCVと組み合わせる予定なので、C++で書けると扱いやすい。GStreamerはC言語で書かれたライブラリだが、C++ラッパーのgstreamermmが用意されているので、これを使うことにした。

GStreamer公式の説明ページにはチュートリアルがいくつか用意されている。今回は最初のチュートリアル1を、gstreamermmを使って書いてみた。

開発環境

ライブラリのインストール

Homebrewを使って必要なライブラリをインストールした。

サンプル動画を再生するために、libvpxおよびlibvorbisとのリンクが必要。また brew link --force gettext が必要になる。これを行わないと、書いたプログラムのリンクの際に「libintlが見つからない」というエラーが出た。後に問題が発生したら brew unlink gettext を行う必要があるかもしれない。

brew install pkg-config gstreamer gst-plugins-good gettext
brew install gst-plugins-base --with-libogg --with-libvorbis
brew install gst-plugins-bad --with-libpng --with-libvpx
brew link --force gettext

ソースコード

CMakeLists.txt

CMake 簡易まとめ」を参考にした。

cmake_minimum_required(VERSION 3.0)
project(tutorial CXX)

find_package(PkgConfig)
pkg_check_modules(GSTREAMERMM REQUIRED gstreamermm-1.0)

set(CMAKE_CXX_FLAGS "-std=c++11 -Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-g3 -O0 -pg")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -s -DNDEBUG -march=native")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g3 -Og -pg")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -s DNDEBUG -march=native")

add_executable(tutorial01 tutorial01.cpp)
target_include_directories(tutorial01 PUBLIC ${GSTREAMERMM_INCLUDE_DIRS})
target_link_libraries(tutorial01 ${GSTREAMERMM_LIBRARIES})
target_compile_options(tutorial01 PUBLIC ${GSTREAMERMM_CFLAGS_OTHER})

tutorial01.cpp

チュートリアルのコードをgstreamermmを使って書き直した。

#include <gstreamermm-1.0/gstreamermm.h>

int main(int argc, char* argv[]) {
  // GStreamerを初期化する
  Gst::init(argc, argv);

  // パイプラインを構築する
  Glib::RefPtr<Gst::Element> pipeline = Gst::Parse::launch(
    "playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm"
  );

  // 再生を開始する
  pipeline->set_state(Gst::STATE_PLAYING);

  {
    // エラーまたはEOSまで待つ
    Glib::RefPtr<Gst::Bus> bus = pipeline->get_bus();
    Glib::RefPtr<Gst::Message> msg = bus->pop(
      Gst::CLOCK_TIME_NONE, Gst::MESSAGE_ERROR | Gst::MESSAGE_EOS
    );
  }

  // リソースを解放する
  pipeline->set_state(Gst::STATE_NULL);

  return 0;
}

C言語で書かれたチュートリアルのコードは以下のとおり。

#include <gst/gst.h>

int main(int argc, char *argv[]) {
  GstElement *pipeline;
  GstBus *bus;
  GstMessage *msg;

  /* Initialize GStreamer */
  gst_init (&argc, &argv);

  /* Build the pipeline */
  pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);

  /* Start playing */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  /* Wait until error or EOS */
  bus = gst_element_get_bus (pipeline);
  msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

  /* Free resources */
  if (msg != NULL)
    gst_message_unref (msg);
  gst_object_unref (bus);
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  return 0;
}

ビルド

CMakeの慣習に従い、buildディレクトリを作ってその中でビルドする。

cd /path/to/tutorial01
mkdir build
cd build
cmake ..
make

実行

ビルドしたら以下のコマンドで実行することができる。

./tutorial01

実行するとウィンドウが表示され、https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm の再生が始まる。最後まで再生されると終了する。

f:id:ochaochaocha3:20170808235748p:plain

C言語で書かれたものとの違い

生ポインタの代わりにGlib::RefPtrを使う

例えば GstElement * 型が返る関数のgstreamermm版では Glib::RefPtr<Gst::Element> が返る。

Glib::RefPtr(リファレンス)はglibmmが提供する参照カウンタ式のスマートポインタクラスで、C++11のstd::shared_ptrに似ている。デストラクタでカウントが1減り、0になったときにリソースが解放される。このスマートポインタのおかげで、gst_object_unref() に相当する ->unreference() を呼び出さなくてもよくなる。

上のコードではポインタを使用する範囲をブロックにした。ブロックを抜ける際にデストラクタが呼ばれ、C言語版とほぼ同じ場所で ->unreference() が呼ばれることになる。

一部の関数のインターフェースが異なる

多くの関数のgstreamermm版はC言語版からの規則的な変換で書けるが、一部インターフェースが異なるものがある。上の例だと、gst_bus_timed_pop_filtered() に対応する関数は Gst::Bus::pop(Gst::ClockTime timeout, Gst::MessageType message_type) と、オーバーロードを利用したものになっている。

一つ一つドキュメントから探していけば良いのだが、インターネットでは現在の最新版1.8.0のドキュメントのページが空になっているため、少し不便になっている。gstreamermmをHomebrewでインストールした場合は /usr/local/opt/gstreamermm/share/doc/gstreamermm-1.0/reference/html/index.html からDoxygenで生成されたドキュメントを見ることができた。未確認だが、Linuxではlibgstreamermm-1.0-docのようなパッケージをインストールすれば閲覧できそうだ。

感想

常にリソース管理に注意しなければならないC++なので、スマートポインタでリソースの解放し忘れが減ることが嬉しい。慣れていないのでまだドキュメントを何度も見ているが、もともとGStreamerがオブジェクト指向で書かれているので、対応するgstreamermmの関数を見つけるのは難しくなかった。個人的にはC++11以降の書き方が気に入っていて、できるだけC++で書きたいと思うので、今後も積極的にgstreamermmを使っていきたい。


  1. 制御するためのLinux用ライブラリがGitHubで公開されている:
    https://github.com/TheImagingSource/tiscamera

2016-11-18 の日記

「標準課題」というグループ課題で、友達の班に「C言語でメールを送れるようにしたい」という要望があった。おもしろそうだったので、放課後に実験を一緒にやってみた。

構成

学校にはファイアウォールがあってインターネット上のSMTPサーバに直接アクセスすることができないようだったので、とりあえず課題用に配られたRaspberry PiSMTPPOP3/IMAPサーバとすることにした。Raspberry Piにユーザーアカウントを作り、Maildirにメールが届くようにする。

前提

ユーザーアカウントは事前に作ってあり、ログインできるものとする。なければ useradd -m someone で作っておく。

Postfixのインストールと設定

Raspbian Jessieを使っていたので、Debian 8での設定手順がそのまま使える。「Debian 8 Jessie : MAILサーバー : Postfix インストール/設定 : Server World」を参考にした。実験用で外に出すつもりがなかったし、時間の余裕があまりなかったので、以下の点は変えた。

  • インストール中、構成のプリセットの選択で「ローカルのみ」を選んだ。
  • 容量制限やSMTP-Authの設定をしなかった。

SMTPサーバの確認

初めにmailutilsを入れてmailコマンドを使えるようにした。

sudo apt-get install mailutils

また、RaspbianではMAIL環境変数が設定されていなかったようなので、以下の内容で /etc/profile.d/mail.sh を作ってログイン時に設定されるようにした。

export MAIL=$HOME/Maildir

反映させるため、一旦ログアウトして再度ログインする。

続いてsendmailコマンドで自分宛てにメールを送った。

sendmail ocha@example.org
# 以下は標準入力
From: ocha@example.org
To: ocha@example.org
Subject: Hello

Hello world!
.

送信後、mailコマンドで確認すると、送ったメールが届いていた。

C言語でメールを送るプログラムを作る

sendmailコマンドを呼び出して標準入力に書き込めばメールを送信できたので、popen(3)でそれを行う。エラー対策等は厳密ではないので注意。

/*
 * send-hello.c
 */

#include <stdio.h>

int main(int argc, char* argv[]) {
  if (argc != 3) {
    fprintf(stderr, "Usage: %s NAME ADDRESS\n", argv[0]);
    return 1;
  }

  char* name = argv[1];
  char* address = argv[2];

  char sendmail_command[256];
  snprintf(sendmail_command, sizeof(sendmail_command),
           "sendmail %s", address);

  FILE* sendmail = popen(sendmail_command, "w");
  if (sendmail == NULL) {
    perror("popen");
    return 1;
  }

  fputs("From: ocha@example.org\n", sendmail);
  fprintf(sendmail, "To: %s\n", address);
  fputs("Subject: Hello\n\n", sendmail);
  fprintf(sendmail, "Hello, %s!\n", name);
  fputs(".\n", sendmail);

  pclose(sendmail);

  return 0;
}

使うときはこのような形で。

./send-hello ocha ocha@example.org

Dovecotのインストールと設定

最後にPOP3/IMAPサーバとしてDovecotをインストールして、メールソフトから受信したメールを見られるようにした。Postfixと同様に「Debian 8 Jessie : MAILサーバー : Dovecot インストール/設定 : Server World」を参考にした。

PCのThunderbirdIMAPサーバとしてRaspberry PiIPアドレスとポート番号143を指定して、上のプログラムを使って送信したメールを受信できることを確認した。

感想

調べながら作業を行ったので時間がかかったが、要点を押さえればそれほど複雑ではない印象だった。

sendmailコマンドはなかなか便利。ちょうど学校でプロセス関連のシステムコールやライブラリ関数の使い方を習った後だったので、良い応用例だった。Raspberry Piなら、ハードウェアの制御と合わせればおもしろいものができそう。

HHVMのコンパイルエラー対策

スーパーロボット大戦Wiki等のMediaWikiを動かすためのHHVMを3.14.2に更新しようとしたときに、まずCMakeで失敗した。これはサブモジュールを再帰的にすべてダウンロードできていなかったためで、以下のコマンドを実行することで次に進めた。

# gitでcloneしたHHVMのディレクトリで
rm -rf third-party
git submodule update --init --recursive

しかし、その後makeするとコンパイルエラーが起きて止まってしまった。コンパイルに失敗するのは hphp/hack/src/server/serverError.ml で、探してみたところ以下のissueが見つかった。

Fixed Datetime comparison with milliseconds involved by wjzijderveld · Pull Request #6888 · facebook/hhvm

新しいバージョンではだめなのかと3.14.1等バージョンを戻して試してみるもどうもうまくいかない。さらに探してみると、以下のissueが見つかり、そこに衝撃の事実が。

jwatzman commented on 31 Dec 2015

ocaml's build systems are terrible when it comes to incremental builds. Can you try rm -rf hphp/hack/src/_build and try again?

Error: Unbound value ServerMonitor.start_monitoring · Issue #6701 · facebook/hhvm」より

訳すと「OCamlのビルドシステムはインクリメンタルビルドになるとひどい。rm -rf hphp/hack/src/_build をやってもう一度試してもらえる?」といったところか。こんな罠は知らなかった…

というわけで、上記のとおりにできたファイルを削除してもう一度ビルドをかけたらすんなり進んだ。しかし3コアのVPSではビルドにかなり時間がかかるようで、2時間弱も待つことに。

OSC 2016 Nagoyaに出展します

2016年5月28日(土)に開催されるオープンソースカンファレンス2016 Nagoyaの浜松職業能力開発短期大学校ブースにて、避難所支援システム「避難所てだすけくん」の展示を行います。

続きを読む

どどんとふの CGI 処理:トップレベル

TRPG のオンラインセッション環境「どどんとふ」の CGI 処理についての解説。前回はこちら。

ochaochaocha3.hateblo.jp

今回からサーバープログラムが書かれている DodontoFServer.rb(コミット 94c3c04)を見ていく。

続きを読む

どどんとふの CGI 処理(構成・インターフェース)

最近は TRPG のオンラインセッション環境どどんとふのソースを読んだり変えたりしていることが多い。TRPG.NET ではオンラインセッションが多く行われる夜間に結構重くなるので、負荷を下げることを目標としている。ソースコードの規模が大きいので、テストコードを追加しながら機能単位での分割などを行い、改善点を見つけやすくしたり部品の再利用を行いやすくしたりしている。

今回から、備忘録を兼ねて、これまで調べたどどんとふの CGI 処理について数回書く。コードへのリンクは ver. 1.47.24 リリース時のコミット 94c3c04 を使うことにする。

続きを読む

2016-04-22 授業日誌

1〜3限

Java等の先生の出張により、まるまる画像処理の時間に。以下のように結構多くのことをやった。

  1. OpenCVの開発環境構築
  2. Webカメラから取り込んだ画像をリアルタイムでウィンドウに表示する
  3. 光とか色とか行列とか基礎事項
  4. 行列演算
  5. 色の分解

OpenCV、グラフィックまわりを手軽に扱えるのでなかなか便利そう。標準課題という今年の後半で行うプチ卒研くらいの量の実習でも使うとのことなので、いろいろと試してみたい。

ところでこの時間のレポートはExcelに全部貼り付ける形で、水曜日のものといい本質的でない部分に時間がかかるので最後は少しうんざり。内容は面白いのだけれど。

2016-04-21 授業日誌

1・2限

アナログ回路設計の実習。LED3個をそれぞれ遅らせて点灯させるウィンカー回路、すべてタイミング通りに点灯させることができた。先生曰く、1個が点いたらその電圧を次の積分回路に回す、というのを繋げていくのが良いとのこと。現状では点いたままになってしまうので、最後に消すための回路が必要。フィードバックする方法を考えていたところで時間切れで終了。電子科出身の同級生がいるグループではそこまでうまくいったという話も聞き、さすがだなぁと感じた。

自宅でシミュレーションをするために帰ってからはLTspiceを入れてみた。適当にフィードバックする回路を組んでみたけれど、過渡特性がイマイチなのでもう少し考える必要があった。

3・4限

Linuxプログラミングの授業。やっとシェルプログラミング。配布資料がちょっとしたリファレンスになっているので、これからサーバー管理のときにそれを見てやることにしよう。内容的にはそれほど目新しいことはなく、最後に配られた演習問題を淡々とこなす。さらに確認テストもあったが、難なく終わった。

2016-04-20 授業日誌

1・2限

Linuxプログラミングの授業。今日はシェルのリダイレクト、パイプとgrepのようなフィルタプログラムがメイン。前提としてファイルディスクリプタシステムコールのかなり丁寧な説明があり、それからリダイレクトとパイプの解説という流れだった。これだけ丁寧に行ってくれれば分かりやすい。去年卒研メンバー間でセミナー的にやったが、授業でこれくらいやってもらえるのはありがたかった。最初からすべて理解するのは大変だが、資料を見直せばなんとかなるだろう。

3限

ARMマイコンの授業。今週はLEDを5個に増やしてみようという内容。ポートの設定を増やすだけなので特に難しいことはない。ただ、宿題がC言語のプログラムを覚えるために手書きで書いてこいという内容だったので面倒だった。プログラムを手書きすること、どれだけ効果があるのだろうか。