タグ「programming」が付けられているエントリー

PHPでTwitterのプロフィール検索してリストを作る方法(OAuth対応版)

| PHPでTwitterのプロフィール検索してリストを作る方法(OAuth対応版)

Twitterのリスト機能って便利ですよね.例えば,イベントなどでその関係者のつぶやきを一覧したい,でもフォローするのはアレだしって時に使えます.同様に,ある共通の趣味を持っている人を集めるとか,ある特定の病気と闘っている人を集めるとか,色々と応用ができます.そんなこんなで,最近はリストを作って喜んでます.

そんなこんなで,今日はTwitter標準のAPIではできないことをサードパーティ製APIで実現しまくる方法を紹介します!具体的には,プロフィールに特定のキーワードが含まれているユーザを抽出して,リストを作る方法です.実装はいつも通りにPHPでOAuth対応です.書き忘れていますが,ソースは当然の如くUTF-8で保存してくださいね.

tps.lefthandle.netのAPIを用いる場合
Twitterのプロフィール検索を提供しているサードパーティは,ざっくり調べた感じでは2カ所あります.そのうちの1カ所がtps.lefthandle.netです.主な仕様としては,GETリクエストに対してJSONで返事します.結果は最大100件で,ユーザー登録順,follower数順,最近のつぶやき順が選べます.というかドキュメント読んで下さい

このAPIを使ってプロフィール検索をして,引っかかった人をリストに追加するコードはこんな感じです.

<?php
$ids = 'yourscreenname';
$listname = 'listname';
$url = "http://api.twitter.com/1/$ids/$listname/members.json";
$q = urlencode('キーワード');
$sortmode = 'recent';//
register, follower
//search APIのURL
$c = curl_init("http://tps.lefthandle.net/rest/?s=$q&sort=$sortmode");
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($c);
curl_close($c);
$json = json_decode($response);
//リストに追加する
foreach ($json as $u) {
$param = array('id' => $u->screen_name);
$res = twitter_api($url, OAUTH_HTTP_METHOD_POST, $param);
}

//twitter api
function twitter_api($url, $method=OAUTH_HTTP_METHOD_GET, $param=null) {
$consumerKey = '
consumerKey';
$consumerSecret = '
consumerSecret';
$oauthToken = '
oauthToken';
$oauthTokenSecret = '
oauthTokenSecret';

try {
$oauth = new OAuth($consumerKey, $consumerSecret,
OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$oauth->setToken($oauthToken, $oauthTokenSecret);
$oauth->fetch($url, $param, $method);
$response = $oauth->getLastResponse();
return $response;
} catch (OAuthException $e) {
return $e;
}
}
?>

ベリーイージーね.前提として,リストは作っておいて下さい.空でも空じゃなくても構いません.もちろん,エラー処理がいい加減なんで,適当に修正して下さい.OAuthのトークンは適当な方法で取得して下さい.この方法だと,検索に引っかかった人を無差別に登録するので,既登録の人を再度登録しようとしたりして無駄が多いので,既登録者リストとの差分を取るとかの工夫をしたら良いんじゃないかと思います.

twpro.jpのAPIを用いる場合
もいっこの方がtwpro.jpです.主な仕様としては,GETリクエストにJSONで返事します.IPアドレス毎に1000回/時のAPIコールが可能です.また,検索結果が最大300件となっています.また,JSONPのコールバックが使えます.使わないけど.まぁ,ドキュメント読んでね.

このAPIを使ってプロフィール検索をして,引っかかった人をリストに追加するコードはこんな感じです.

<?php
$ids = 'yourscreenname';
$listname = 'listname';
$url = "http://api.twitter.com/1/$ids/$listname/members.xml";
$q = urlencode('キーワード');

//search APIのURL
$c = curl_init("http://api.twpro.jp/1/search?q=$q&num=300");
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($c);
curl_close($c);
$json = json_decode($response);
//リストに追加する
foreach ($json->users as $u) {
$param = array('id' => $u->screen_name);
$res = twitter_api($url, OAUTH_HTTP_METHOD_POST, $param);
}

//twitter api
function twitter_api($url, $method=OAUTH_HTTP_METHOD_GET, $param=null) {
$consumerKey = 'consumerKey';
$consumerSecret = '
consumerSecret';
$oauthToken = '
oauthToken';
$oauthTokenSecret = '
oauthTokenSecret';

try {
$oauth = new OAuth($consumerKey, $consumerSecret,
OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$oauth->setToken($oauthToken, $oauthTokenSecret);
$oauth->fetch($url, $param, $method);
$response = $oauth->getLastResponse();
return $response;
} catch (OAuthException $e) {
return $e;
}
}
?>

こんな感じかな?いいんじゃないかな?どっちのAPIも良くできているよ.

別になんら難しいことはないんだけど,TwitterのBOTを作って自動フォローやリムーブをしたくなることってあるじゃないですか?特に,人気BOTになってくると,いちいちフォローされましたメールからフォローするなんて,面倒くさいじゃないですか?そうなると,自動でやりたいですよね.ということで,自動フォロー/リムーブするPHPなプログラムを書いたよ.もちろんOAuth対応版だよ.

<?php
$ids = 'yourscreenname';

$friends = array();
$followers = array();
$list_follow = array();
$list_remove = array();

//APIからfriends取得
$url = "http://api.twitter.com/1/friends/ids/$ids.json?cursor=-1";
$res = twitter_api($url);
$json = json_decode($res);
//ユーザIDを抽出して配列に
foreach ($json->ids as $u) {
$friends[] = $u;
}

//APIからfollowers取得
$url = "http://api.twitter.com/1/followers/ids/$ids.json?cursor=-1";
$res = twitter_api($url);
$json = json_decode($res);
//ユーザIDを抽出して配列に
foreach ($json->ids as $u) {
$followers[] = $u;
}

//followするリスト作成
$list_follow = array_diff($followers, $friends);
//removeするリスト作成
$list_remove = array_diff($friends, $followers);

//followする
foreach($list_follow as $f) {
$url = "http://api.twitter.com/1/friendships/create/$f.json";
$res = twitter_api($url, OAUTH_HTTP_METHOD_POST);
}

//removeする
foreach($list_remove as $f) {
$url = "http://api.twitter.com/1/friendships/destroy/$f.json";
$res = twitter_api($url, OAUTH_HTTP_METHOD_POST);
}


//twitter api
function twitter_api($url, $method=OAUTH_HTTP_METHOD_GET, $param=null) {
$consumerKey = 'consumerKey';
$consumerSecret = 'consumerSecret';
$oauthToken = 'oauthToken';
$oauthTokenSecret = 'oauthTokenSecret';

try {
$oauth = new OAuth($consumerKey, $consumerSecret,
OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$oauth->setToken($oauthToken, $oauthTokenSecret);
$oauth->fetch($url, $param, $method);
$response = $oauth->getLastResponse();
return $response;
} catch (OAuthException $e) {
return $e;
}
}
?>

トークンは自分のものに置き換えてね!どうせBOTだろうからdevelopersあたりから取れるよね.作り方が雑なんで,適当に改変して利用するといいんじゃないかな.

備忘録的メモ.前提条件として,apacheやphpは入っていること,pearが使える状態であること.こっちのOSはUbuntu9.10amd64です.他の環境でも似たようなものです.

PHPでOpenIDなライブラリといえば,php-openidだと思います.2.2系になってから,githubに移行して,docディレクトリが無くなりました.「なんでドキュメントがないんだ,むぎゃ!」って思っていたのですが,やり方がわかったので,メモ.

DOCUMENTATION
=============

You can view the HTML library documentation in the doc/ directory.

This package's documentation is in PhpDoc format.  To generate the
documentation, install phpdoc and run the admin/makedoc.sh script.
Phpdoc lives at:

  http://www.phpdoc.org/

openid's php-openid at master - GitHub

書いてある通りなんですが,ドキュメントはPhpdocなるものを使って作れと言っています.Phpdocの正式名称はphpDocumentorで,pearからインストールできるようなので,入れます.

$ sudo pear install --alldeps PhpDocumentor

簡単ね!続いて,ドキュメントをmakeするよ.ディレクトリとかは適宜読み替えて下され.

$ unzip openid-php-openid-2.2.2-0-ga287b2d.zip
$ cd openid-php-openid-782224d
$ chmod +x admin/makedoc.sh
$ admin/makedoc.sh

簡単ね!これでdocにドキュメントができあがります.

参考:
How to install PhpDocumentor on Ubuntu | greenhughes.com

以前,GDD2010のDevQuizに参加している旨を書いたわけですが,とっくに締め切られてて,今日の0時頃から順次結果発表が行われていた.起きている時間には結果が届かなかったのだが,朝起きたら届いていた.

クイズの解答を審査した結果、見事、参加の基準点をクリアされました。おめでとうございます。

とのことで,めでたく審査を突破して,GDD2010JPに参加できるようです.まぁ,当日はCF検査なんで,終わり次第に向かうわけですが・・・.朝から参加したかったなぁ・・・orz.

ところで,クイズをどのくらい解いたのかっていえば,それほど解いていない.

100904_devquiz01.jpg

PAC-MANに挑戦していないし,Google Maps APIも途中でさじを投げた.それ以外で解答できるものは全部解いたわけですが・・・.うーん.この程度も通ってしまうとはorz.

Twitterの情報によると,定員割れではないのかとの予測.それっぽいですよね.これしか解いてないのにorz.

まぁ,それはそれとして,GDD2010JPに参加できるようです.よかったよかった.

関連:
Google Developer Day 2010 DevQuiz - 4403 is written

201009152235追記:

100915_gdd2010jp01.jpg

えっ?

今年の夏の自由研究を何やるか決められないまま,既に夏休みなんですが,どうしましょう?と思っていたところ,タイミング良くGoogle Developer Day 2010 DevQuizが始まったので,参加中です.脳味噌コネコネにはちょうど良いです.昨晩から参加して,今のところ,こんな感じです.

gdd2010devquiz01.jpg

とりま,共通問題はサクッとやって,HTML5間違い探しもサクッと終わらせました.認証屋としてOAuthができないなんてのは問題外(というかそういうデモを作ってるくらいだし)なので,サクッとPHPで挑戦して,ムリってなりましたw.Pecl::OAuthはダメだ.realm指定できないw.仕方ないから,PerlのOAuth::Lite::Consumerを使いました.パッケージのスペルを間違えてて,小一時間悩んだのは良い思い出.

んで.Top Favoritesは一切何も関与していないことが判明したので,Super HackersかNext Generationに応募するしかないので,とりま,Super Hackersに挑戦中です.Shiritoriはレベル2までは適当にブルートフォース的なやり方で解けました.レベル3は単語数が増えるので,プログラムを作って挑みました.実装はC言語で.なんとなくPerlの方が簡単に作れた気がする・・・.久しぶりの再帰関数にちょっと四苦八苦しながら,見事に撃退しました.ちなみに,相手の手のことを考えていなくて,解答が合わなくてパニクったのは良い思い出.

残るはPAC-MANとエッセイです.エッセイはまぁいいとして,PAC-MANをどうするかなぁ・・・.これは結構マジで作らないとダメだよなぁ・・・.そもそもパックマンは苦手だから,戦略アルゴリズムを立てられないorz.

というわけで,PAC-MANは置いておいて,解けそうなGoogle Maps APIをやろうかなと思っている.中身的にはMaps APIを叩いて最短経路問題を解けばいいので,高々10点らしいので,マップを作ってダイクストラ法の総当たりでフィニッシュです.でも,手元にダイクストラのプログラムがないので,自宅に戻ってから.

まとめ:
なかなか楽しいです!全く解法が解らないでもなく,めちゃめちゃ簡単でもない.挑戦しがいのある問題って素敵.ところで,GDD2010の開催日が9月28日で,大腸内視鏡検査とバッティングしそうなんだよね・・・.無駄に終わるかもしれんorz.

ちょっと所用があるので,OpenID AXを喋るOPとRPを作ってみた.厳密に言えば,作ってみたではなく動かしてみたなのだが,ネット上に情報が少なすぎる,特にAXを喋るOPの情報が皆無に等しいので,とりあえず書き残しておく.実装はOpenID EnaledのPHP Library 2.1.3を使いました.PHPは5.3系で上手く動かなかったので,5.2.10でやってます.apacheは2.2.12で,OSはUbuntu9.10x64です.

AXを喋るRPの実装
まずはRP側を実装します.examples/consumerを用いれば,RPは簡単に作れます.しかも,サンプルにはSregとPAPEを喋るように作られています.まぁ,普通に動かせば動きます.んで,AXを喋るようにいくつか改変します.基本的にAXはSregやPAPEと同じExtensionなので,参考にしながら実装します.実装に当たっては,当然ながらドキュメントが役に立ちます.読みにくいですけどね.

まずはcommon.phpをいじります.AX関連のクラスを使いますので,doIncludes()の中で,require_once "Auth/OpenID/AX.php"しておきます.papeを参考にすると,ここらで定数などを宣言しているようなので,真似して宣言してみます.

global $ax_attributes;
$ax_attributes = array(
'http://axschema.org/contact/email' => 'email',
'http://axschema.org/namePerson/first' => 'firstname',
'http://axschema.org/namePerson/friendly' => 'nickname');

属性型はaxschema.orgにしました.別に他のでもいいです.次に,index.phpを変更しておきましょう.PAPEの部分を参考にします.というか,バッサリ頂きます.61-67行目を以下のように置き換えちゃいます.

<p>Optionally, request these attributes:</p>
<p>
<?php
global $ax_attributes;
while (list($key, $val) = each($ax_attributes)) {
print "<input type=\"checkbox\" name=\"ax_requests[]\" value=\"$key\" checked />";
print "$key ($val)<br/>";
}
?>
</p>

恐ろしく汚いコードですが,気にしたら負けです.これでIdentifierの入力を尋ねるときに,要求するAXを3種類の中から選べるようにしています.デフォでは全部ONですが. 続いて,try_auth.phpをいじります.まず,SregとPAPEは使わないので,該当部分をバッサリ捨てます.30-38行目がSregで,40-45行目がPAPEなので,コメントアウトするなり,消しちゃうなりして,機能しないようにしておきます.で,この辺りにAXのコードを書きます.

global $ax_attributes;
$ax = new Auth_OpenID_AX_FetchRequest;
$ax_uris = $_GET['ax_requests'];
while (list($key, $val) = each($ax_attributes)) {
if(in_array($key, $ax_uris)) {
$attribute[] = Auth_OpenID_AX_AttrInfo::make($key, 1, false, $val);
}
}
foreach($attribute as $attr){
$ax->add($attr);
}
$auth_request->addExtension($ax);

3行目の$_GET['ax_requests']はindex.phpのチェックボックスからどの属性がリクエストされたかを受け取っています.そんで,その要求されたものを$ax_attributesと比較して,Auth_OpenID_AX_AttrInfoでAXのリクエストにあうように準備します.ちなみに,第3パラメータをfalseにしているので,要求する属性はrequiredではなく,if_availableになります.そんで,$ax->add($attr)で属性セットして,最後にextensionに追加する感じです.このコードはExample usage of AX in PHP OpenIDを参考にしました. 最後に,finish_auth.phpを書き換えます.SregとPAPEを無効にしたいので,41-90行目をバッサリと消しちゃいます.かわりにAX用のコードを書き加えます.

$ax_resp = Auth_OpenID_AX_FetchResponse::fromSuccessResponse($response);
$success .= '<dl>';
global $ax_attributes;
while (list($key, $val) = each($ax_attributes)) {
$ax_data = $ax_resp->get($key);
if(!is_object($ax_data)) {
$success .= "<dt>$val</dt><dd>$ax_data[0]</dd>";
}
}
$success .= '</dl>';

特に解説することもないですけど,AXの返事は$ax_resp->get($key)で取り出しています.Type URIをキーにして,取り出しています.コードを見ればわかると思いますが,何を要求したとか,何が返ってきているかは全く考えず,総当たりにチェックしてます.大した量じゃないし.そのため,!is_object($ax_data)でエラートラップしてます.getメソッドで取り出せなかった場合,Auth_OpenID_AX_Errorが返りますので,objectかどうかのチェックでさばいてます.複数の属性値が返ってきた場合でも最初の1つしか表示しない辺りも詰めが甘いですが,気にしないで下さい.気になるなら,自分で工夫して下さい.僕には必要がないコードです.

AXを喋るOPの実装
続いて,OP側を作ります.examples/serverを使います.こっちが結構に四苦八苦でした.勝手にはまっただけですけど.こっちはいじくる部分はlib/common.phpだけです.まずはSregとPAPE関連を消し去ります.56-76行目がSregで,PAPEは・・・ないですねw.なんだ,OP側のPAPEは実装されていないのか.それはそれとして,Sregが書いてあった辺りに,AX用のコードを書き加えます.

$attributes = array(
'http://axschema.org/contact/email' => 'email@example.com',
'http://axschema.org/namePerson/first' => 'first',
'http://axschema.org/namePerson/friendly' => 'nickname');

$ax_requested = Auth_OpenID_AX_FetchRequest::fromOpenIDRequest($info)->getExtensionArgs();
$ax_response = new Auth_OpenID_AX_FetchResponse();
while (list($key, $val) = each($attributes)) {
if(in_array($key, $ax_requested)) {
$ax_response->addValue($key, $val);
}
}
$ax_response->toMessage($response->fields);

実に,このコードにたどり着くまでに苦労しました.何にはまっていたかは後で説明します.コードは解説する必要がないくらいに簡単です.$attributes[]の中は連想配列でType URIをキーとして,属性値を格納します.んで,$ax_requestedと比較して,リクエストされている属性を$ax_response->addValue($key, $val)でセットします.以上で完成です.

動作例

100608_ax01.jpg

これはRP側です.http://localhost/rp/です.色々突っ込みどころ満載ですが,デモですからスルーして下さい.Identity URLのところに,自前OPのidentifierを入れます.AXで取得したい属性をチェックボックスから選びます.とりま,全選択で.

100608_ax02.jpg

こっちがOPからの返事を受け取ったRPです.要求した属性が全て取得できています.下の黄枠の中にはAXレスポンスの内容を表示してみました.aliasがext0とかになっています.ここで勝手にはまってました.結果的には,これで良かったんです.問題なく動いています.これで,AXを喋るOPとRPはできあがるので,後は煮るなり焼くなり・・・.

はまったところ
OPのレスポンスを作るのに苦労しました.というか,勝手な思い込みです.上記で示したOPのコードでAXを喋らせると,違和感があったんです.例えばこのエントリで例示されているように,ax.type.nicknameでリクエストしたら,レスポンスもax.type.nicknameとax.value.nicknameで返るのが自然のように思います.僕もそうだと思っていましたが,これは全然どうでもいい話でした.ここで例示したnicknameというのはaliasなのですが,aliasについては以下のように書かれています.

The <alias> will further be used to identify the attribute being exchanged.

Final: OpenID Attribute Exchange 1.0 - Final

とのことですので,identify出来ればよろしく,何だっていいようです.なので,ここではnicknameでリクエストしても,レスポンスはfriendlyでもいいわけです.問題なのはレスポンスにおいて,friendly.typeとfriendly.valueが紐付きますので,その関係だけが保たれていれば,aliasは何でもokです.

実際のところ,上記に示したOPが喋るAXはレスポンスとしてext0とかext1というaliasを張ります.最初はこれをみて正規の手続きでやっていないからまずいんだと思い込み,AX.phpやMessage.phpの中にまでダイブして,色々と調査しました.で,追っていけば行くほど,コードは正しそうに見えてくるんです.おかしいと思って確認してみたところ,さっきの例示したエントリでも,profile_imgでリクエストして,imageでレスポンスされている.つまりまとめると,重要なのはaliasではなく,Type URIである.aliasは一意ではない(そんな定めがない)が,Type URIは一意なので,そっちを見ろということである.なるほど当然の道理である.

まとめ:
PHPでAXを喋るOPとRPを実装した.簡易版なので,色々と不十分な実装(特にOP側)となっているが,実証コードには十分である.

201006081344追記:
Apache License 2.0らしいので,10はてブ超えたらソースコード公開する.

ずっと前から書こう書こうと思っていたものをヴァァァーーーーに任せて書こうと思う.「お金が無くてオフィスが買えない!」という人や「金を払うのがばからしいから不正コピーでチーッス」っていうバカのための,ソフトウェアは全部無料でありながらも,まともに研究や勉強ができる環境を準備するお話です.不正イクナイ!

前提:とりあえずパソコンはある(XP時代のもので十分です)

さて,早速ですが,無料のOSから手に入れてみたいと思います.MicrosoftのWindowsはパソコンを買うとついてきますが,基本的に有料です.パソコン代にOS代が含まれているんですよ!Macのことはよく知りませんが,間違いなく有料だと思います.というわけで,それ以外の選択肢となると,思いつくのがLinuxです.というわけで,オレご贔屓のUbuntuを使いたいと思います.また,今回は調子をぶっこいて最新版すぎるDaily BuildなLiveCDを使いたいと思います.i386かamd64のどちらか適切なisoファイルをダウンロードしてください.わからなければ,i386を選んでください.なお,isoのダウンロードは後述のUNebootinでも可能ですが,速度が出にくいので,先にダウンロードしておく方法をオススメしました.どちらでも結構です.

さて,ダウンロードができたらインストールの準備を始めます.isoイメージなので,CDに焼いてしまえば良いと思いますが,最近の流行はUSBメモリブートです.ということで,UNetbootinというツールを利用します.1GB以上あるUSBメモリをPCに差し込んで,ソフトを起動します.なお,ここでisoイメージをダウンロードして自動でゴー!ってしたい方は1番上のDisribuionからUbuntuを選んでDaily_Liveを選びましょう.

100420_ubuntu01.jpg

こんな感じで,さっきダウンロードしたisoファイルを指定して,USBメモリが指定されていることを確認して,okを押します.あとはメッセージに従ってください.なお,USBメモリの中身は消えちゃいますので,その辺だけは注意してください.完成したら,USBメモリからブートさせてください.Ubuntuが起動するはずです.

なお,これ以降の説明は実機ではなくVMware上で行っていますが,基本的に同じですので,気にしないでください.仮想環境を作りたかったんだよー.だからついでに書いているんだよー.ちなみに,VMwareにインストールしたら,簡易インストールがなんたらですごく簡単にインストールできた旨をお知らせしておきます.いや,普通にやっても簡単だけどさ.

100420_ubuntu02.jpg

さて,それはさておき,作成したUSBからブートしたUbuntuはこのような感じだと思います.

100420_ubuntu03.jpg

このまま利用しても良いのですが,常用するのでハードディスクにインストールします!赤枠で括ったアイコンをクリックしてインストールします.手順は割愛しますが,ガイド通りに進めば良いと思います.インストールが終わったらUSBメモリを抜いて,再起動させます.もう終わりに近いです(ぇ.

100420_ubuntu04.jpg

インストール完了後にはもちろんアップデートです!と行きたいところですが,daily buildを使っているので,何もありませんでした.これはこれでつまらない・・・.さて,それでは利用環境を準備していきましょう.

なにはなくともインターネット!とにかくブラウジング!
クラウド時代においてインターネットは重要です.デフォでFirefoxが入っていますので,これを使っても良いと思います.でも,今日はGoogle chromeを入れてみたいと思います!chromeをダウンロードするためだけに,Firefoxを使いましょう(ひどい・・・)!それっぽいのをポチポチ押していって,最後は自動実行に任せてえいや!です(伝わってるかなぁ・・・).パッケージインストーラが起動すると思うので,そのままインストールをポチッとな!

100420_ubuntu05.jpg

こんな感じでパネルに追加すると便利です.これでokです.サクサクです.楽ちんです.

いやいや!オレyoutubeとかニコニコとかみたいねん!
パッケージマネージャを利用して「ubuntu-restricted-extras」をインストールだ!「依存により要求された変更を追加しますか?」と聞かれるので,迷わずにマークを選択でFA.最後に適用ボタンを押しておk.

100420_ubuntu06.jpg

簡単ねっ!

論文読みたいな!PDF!PDF!
Adobe Readerを入れるでもいいんですが,入れなくても普通に開けちゃいます.この辺がWindowsと違うところです.良い感じ♪Adobe Readerを入れる場合はこの辺からインストール

Microsoft Officeが使いたい!
Microsoftのオフィスはないけど,類似品のOpenOffice.orgはあるんです.

100420_ubuntu09.jpg

↑これがワードのかわりのWriterさん.

100420_ubuntu08.jpg

↑エクセルのかわりのCalcさん.

100420_ubuntu07.jpg

↑パワーポイントのかわりのImpressさん.

ちなみに,Googleドキュメントを使うという手もあると思います.悪くないですよ?OOoもGoogleドキュメントも,すごいんだぜ?保存する時にPDFで保存できるんだぜ.優しいね.優しさがにじみ出てるね.

C言語でプログラミングの勉強をしたい!
すればいいじゃん(え.標準でインストールされているはずです.安全のために,パッケージマネージャからbuild-essenialを入れておきましょう.あとは普通にプログラムを書いて,コンパイルして,実行です.コンパイルなどの手順は以下の通り.

$ vim foo.c
$ gcc foo.c
$ ./a.out

簡単だねっ!え?VisualStudioみたいな統合環境が良いだって??そしたら,パッケージマネージャでgeanyってのを入れると良いと思うよ!

100421_ubuntu01.jpg

まぁ,eclipseを入れても良いとは思いますが,依存パッケージが多いので,インストールに時間がかかりますよ?仰々しいプログラムを書くなら,eclipseもよろしいかと.インストールは同じくパッケージマネージャからeclipseを.日本語化とかC言語用の環境準備とか面倒くさいですよ?英語の勉強を兼ねて,英語のままで使うってのも良いかもしれません.

さてそろそろ論文書くか
TeXの出番ですね?わかります.でも,今日は疲れたよ.また今度にしよう!そうしよう!

参考:
軽量アプリを厳選し、Ubuntu 10.04 β2を入れた4GBのUSBメモリでブートした古いノートPCで仕事してみた | Viva! Ubuntu!!
Ubuntuで C言語を使おう | 不定期ソフトウェア開発

scis2010.png

SCISは宮崎からの参加で,今年は3年目になります.CSS×2.0デビューはしていますが,SCISナイトセッションにはデビューしていませんでした.今回,ひょうんなことから「理論と実装のギャップ(仮)」というタイトルで発表の機会を与えられましたので,全力で挑んできました.

SCIS2010ナイトセッション「理論と実装のギャップ(仮)」

発表資料は公開します.ナイトセッションで使わなかったスライドには右上に赤丸が表示されています.基本的には変更していませんが,一部を修正しています.なお,プログラムソースが見えると思いますが,見ないで下さい.

ナイトセッションでは研究速報枠を3分ほどいただきました.どの辺が研究速報なのかは不明ですが・・・.真面目な内容にもかかわらず,やや受けをいただいて,嬉しい限りです.みんなやさしい!

なお,この発表の様子はyoutubeで公開されています.別ソースもあるのですが,公開していいのかどうか・・・.

関連:
素因数分解twitterボットfactoring_botを作りました - 4403 is written
SCIS2009ナイトセッションの資料 - 4403 is written
CSS×2.0 in CSS2008 - 4403 is written
CSS×2.0 in CSS2009 - 4403 is written

まだ夏の自由研究が終わっていない気がしますが,冬の自由研究を決めました.冬はGoogle Chromeの拡張機能を書いてみようかと思っています.HTMLとJavaScriptで書けるらしいので,まぁなんとかなるかなって.JSが心配だけど.これが上手くいった暁にはお蔵入りしているid:d:kakku22との共著論文を再投稿したいと思う.っていつの話やねん!って言われかねないw.

関連:
「HTMLとJavaScriptで作れます」、グーグルが「Chrome拡張」を解説 - ニュース:ITpro
GoogleChromeの拡張を作る上でFirefoxアドオン作者が知っておくべき10の違い【GoogleChromeでニコ動拡張を作ってみた感想】 - love_firefoxportableの日記
青図~夏の自由研究 - 4403 is written
夏の自由研究が頓挫しそうな件について - 4403 is written
夏の自由研究をまだやっている件 - 4403 is written
CSS×2.0 in CSS2009 - 4403 is written

たぶん,まだ誰も書いていなさそうだから,勢いで書いてみる.今日公開になったような気がするGoogleの新しいプログラミング言語であるGoをUbuntu9.04(x86_64)で動かしてみる.てか,最初は失敗したんだ.なのに,ここの説明通りにやったら成功したんだ.何も違わないのに・・・.なので,手順はそのままです.

$ cd ~
$ mkdir bin
$ export GOROOT=$HOME/go
$ export GOOS=linux
$ export GOARCH=amd64
$ export PATH=$PATH:$HOME/bin
$ source .bashrc
$ sudo apt-get install python-setuptools
$ sudo easy_install mercurial
$ hg clone -r release https://go.googlecode.com/hg/ $GOROOT
$ sudo apt-get install bison gcc libc6-dev ed
$ cd $GOROOT/src
$ ./all.bash
$ cat >hello.go <<EOF
package main
import "fmt"
func main() {
  fmt.Printf("Hello, Go!\n")
}
EOF
$ 6g hello.go
$ 6l hello.6
$ ./6.out
Hello, Go!
$

動いた.そんだけ.

関連:
The Go Programming Language
新プログラミング言語「Go」をCentOSにインストールしてみた « zaru blog

初めてjQueryを使った(やや嘘を含む)のだが,包み隠さず正直にその感想を述べるならば,「超便利」の一言に尽きると思う.JavaScriptでの実装をしたことがないわけではなく,普通のJSとPrototype.jsを少々.本格的にJSで何かを書いたことはないです.そんなボクが,やめればいいのに,クライアントサイドだけでグリグリ動くアプリを作ることに.一応,ほかの言語も検討しました.C言語とPHP.どっちも向かなさそうだったので,JSに頼った次第です.

JSを選んだのには理由があって,Twitterでもつぶやいた(誰も反応しなかったけど)んですが,Pubsubhubbubデモみたいなのを作りたかったんです.

http://www.youtube.com/watch?v=ewQBgbysSOQ&fmt=18#t=2m45s 大まじめなつぶやき.pubsubhubbubのデモvideoにある追加されたのがリアルタイムに更新されていく見せ方はどのように実装するんですか??

Twitter / 4403: http://bit.ly/AAYTg 大まじめなつ ...

で.いろいろと調べた結果,jQueryでできるらしかったのです.それがshow()とhide()なんです.そんなわけで,jQueryでプログラムを書いてみたんですが,テラ便利.何が便利かって,充実のプラグイン.かゆいところまで手が届きすぎます.車輪の再発明は不要なので,ライブラリをグリグリ使わせていただいて,自分が手を加える箇所は最小限に.怠けているんじゃないよ?コードの信頼性を上げているんだよ.オレの書くコードなんて信用ならないもんね.それから「そんなことまでできるの!?」と驚きを隠せないのが,jQuery UI.カラーピッカーやスライダーが秒殺実装可能です.

あとは,なんといっても,Ajaxも簡単にできます.AjaxはJSの醍醐味ですね(ちがう?).当初はサーバサイドにもスクリプト(PHPでやるつもりだった)をおいて,JSONでAjaxな感じを思い描いていたわけですが,想定外にjQueryが強力で,クライアントサイドだけで事足りました.すごいぞ!jQuery!デレデレです.

まとめ:
jQueryラブ. 

関連:
jQuery: The Write Less, Do More, JavaScript Library
Plugins | jQuery Plugins
jQuery UI - Home
jQuery 1.3.2 日本語リファレンス
jQuery入門 – ポンクソフト
jQuery 開発者向けメモ

前回,頓挫しそうだったのでぼやいたら,アドバイスをいただいたので,それに従って追試をしてみた.

まず,そもそもQRコードは読めるのか論だが,qr.quel.jpqr-coder.comの両方で作成したものをそのままlibdecodeqrにかけてみたところ,問題なく読み込めた.素材として,使える.

090924_qrcode01.png

続いて,これを印刷して,ARToolKitベースのあれで読み取って,射影変換したQRコードをlibdecodeqrに食わせてみた.結果からいえば,失敗.が.理由は単純で,QRコードの周りに適切な余白をつけることで,デコードできました.

090924_qrcode02.png

おおむね良好.

ということで,今後プログラムに起こす(連続かつ自動で流れるように)べきこと.

  1. QRコードの四隅の座標を取得する
  2. ネガポジ反転する(てか二値化を反転させておけばいい?)
  3. 射影変換する
  4. 周りに余白をつける
  5. libdecodeqrにデコードさせる

うん.だいたいの道筋はできたし,できそうな気配を感じ取った.射影変換に苦労しなくて良かったのは,画像処理屋でない視点からして嬉しい.

夏の自由研究の話なんですが,結構やばいです.図で説明します.

090918_qr01.jpg

こはカメラから取り込んで,二値化処理をしたQRコードと思われる部分です.うまくとれます.これはok.

090918_qr02.jpg

これは二値化して切り取ったQRコード(傾いている)を射影変換したもの.コードはOpenCVです.うまくいってます.これもok.後は,これをQRコードとしてデコードすればよろしい.

090918_qr03.jpg

これがいただけない.射影変換したQRコードをネガポジ反転して,QRコードデコーダであるlibdecodeqrに放り込んだ様子.ステータスコード2009(16進数だよ!)はエラーコードによりますと,以下の通りです.

  • QR_IMAGEREADER_DECODED 0x2000
  • QR_CODEDATA_NOT_SUPPORT_ECI 0x0001
  • QR_CODEDATA_UNRECOVERABLE 0x0008

重傷じゃん!どうすっかなー?こんなにきれいに復元できても,サポート外とか・・・.んなバカなって話ですよ.特定のQRコードしか読めないのかしら??それとも,このQRコードが亜種なのか.QRコードデコーダを自力で書かなくてはならないのだろうか・・・.ボスケテ!

200909200947追記:
nitechの先生からコメント頂きました.P906iでデコードできないそうです.iPhone 3GSの場合,QRコードが悪いのかリーダが悪いのか特定できないくらいに性能が悪いので,旧ケータイのW53CAを使ってみた.結果としては「24」とデコードできました.うーん.これはこれで困る結果だ.どうしよう・・・.

090812_overview01.png

やろうとしていることは,上図のような感じです.QRコードをデコードした後はどうするのかという話は,また別.初音ミクでも表示させておけば良いんじゃないかと思っている.おそらくは,そこから先はOpenGLの出番かと.うーん.勉強するべき技術が多いぜ.

何故こんな流れになっているかと申しますと.最初はlibdecodeqr付属のwebcamサンプルを拡張していたんですが,いかんせん歪みに弱く,QRコードをかなり大きめに撮影する必要がありました.これは複数のQRコードを同時に読ませようとする目的からして,かなり厳しいです.なので,OpenCVで画像処理してやればいいんじゃね?という発想からきています.射影変換等で多少変になっても,RS符号によって誤り訂正しまくってくれることを期待しています.そうすると,今度はOpenCVに処理させるべきQRコードと思われる部分をどのようにして切り出すかという話になるので,それはARToolKitに押しつけた形です.要するには,自力でコードを書く量は最小限にして,既存技術を最大限に活かそうという考えです.目的の本質じゃないところで苦労したくないんです.

というわけで,こんな感じの流れで実装していますが,「はっ?ばかじゃねーの?そんなの××で一発じゃん?」とか「○○を使ってARToolKitで直接QRの領域切り出せよ」とか「△△なら傾いたQRコードでもデコードするし,みたいな?」なんていうご意見や情報等がありましたら,どしどしとお寄せいただきたいと思います.特に,AR業界や画像処理業界の方々からのご意見をお待ちしております.異分野コラボレーションだ!(いや,マジでなにかご意見下さいorz)

090812_ar01.jpg

今日の成果.あとは,選択された領域を切り取って,射影変換して,libdecodeqrに投げてみる.上手くいけば,上手くいくはず.ただ,残念なことに,QRコード同士が近すぎて誤認識が多いです.領域が正方形に近いかどうかというチェックも必要かしら?実際はこんなに詰まった状態では使わないから,無視でも良いかな?

capture_11082009_012108.jpg

赤枠はイメージです.マーカパターンはhiroを使っているので,パターンをシンボルで作り直せば,もうちょっとちゃんと認識するかと.

libdecodeqrでがんばって,複数(といっても2個)のQRコードを同時に認識させることはできた.理論上は何個でも認識するはずなのだが・・・.Webカメラで読み込んでいたり,QRコードは模様が細かかったり,歪み等の補正を何もしていなかったりと,いろいろな状況が重なり合って,2個が限界の上に,全く安定しない.これは困った.

というわけで,libdecodeqrでがんばるのもどうかと思ったので,ARToolKitとOpenCVとlibdecodeqrを組み合わせる方向でがんばってみようかと思う.

で.結局のところ,基本アイディアはQRコード上の初音ミクに戻るのだが,これはlibdecodeqrを使っていないようだし,座標変換してるみたい.座標変換で平面に持ち込めば,libdecodeqrで認識できると信じている.てか,libdecodeqrは読めないQRコードパターンが多いような気がする.特に,バージョンが高くなるとダメぽ.これはカメラの性能だろうか?

なんだか,気合いの入り具合が間違った方向に向いてきた・・・.まずいまずいまずい.もっとさらっと仕上げる予定だったのに!QRコード上の初音ミクのソースが公開されていないから,こんなに苦労するんだ!(責任転嫁)

ARToolKit拡張現実感プログラミング入門

ARToolKit拡張現実感プログラミング入門
著者: 橋本 直
価格: ¥3129(税込)
出版社: アスキー・メディアワークス (2008/9/17)
ISBN-10: 4048673610
ISBN-13: 978-4048673617

工学ナビで有名な橋本氏が執筆したARToolKitの入門書.今更ですが,買ってみました.6日に注文して,8日に発送されて,10日に到着しました.いやいやまさに,入門書です.授業用の教科書にも使えるかと思います.サンプルもたくさん収録されているので,ARToolKitとはなんぞや?というレベルの方に最適です.中身はそれほどに難しくありませんが,行列がでてくるので,その辺の計算や表記法が分かっていないと,その部分を理解するのは難しいかもしれません.が,分からなくても,動かせますw.試しに動かしてみて,それから納得するのが工学ですよね?

まとめ:
入門には最適.オレには不適.もう1冊の方も買ってみようかな・・・.

調べたけど分からない.決定的なものが見当たらない.MSXMLを使うのが簡単そう.だけど,自宅では環境が足りない模様.明日,開発環境でテストしてみるコード.ちなみに,「実証コードには手間を掛けない」が持論なので,簡単にXMLをパースしちゃう言語をご紹介.「これはひどい」で有名なPHPで.

<?php
$string = <<<XML
<a>
<b>
<c>text</c>
<c>stuff</c>
</b>
<d>
<c>code</c>
</d>
</a>
XML;

$xml = new SimpleXMLElement($string);

/* <a><b><c> を探します */
$result = $xml->xpath('/a/b/c');

while(list( , $node) = each($result)) {
echo '/a/b/c: ',$node,"\n";
}

/* 相対パスでも動作します... */
$result = $xml->xpath('b/c');

while(list( , $node) = each($result)) {
echo 'b/c: ',$node,"\n";
}
?>

PHP: SimpleXMLElement::xpath - Manual

実行結果は以下の通り.

/a/b/c: text
/a/b/c: stuff
b/c: text
b/c: stuff

PHP: SimpleXMLElement::xpath - Manual

xpathもできて,かんたーん.

諸事情で,QRコードを複数認識したい衝動に駆られた.で.libdecoreqrってのが便利らしいので,試してみた.現時点までで分かったこと.

  • OpenCVが予想以上に便利だった
  • libdecodeqrで複数QRコードを認識させるには,外側からのアプローチじゃダメそうなので,中身を弄らないとダメそうなことは理解した
  • QRコードの方がイメージしやすいと思ったんだけど,
  • あきらめてARToolKitで複数マーカ認識にした方が良いだろうか
  • 実はARToolKitはあまり得意じゃないです><;
  • ニコニコ技術部のソースファイル(もしくは考え方)がみたい・・・
  • 具体的にはQRコード上のミク

おなかすいた.

プロフィール

e-m@il @ddress