数ヶ月前に作ってTwitterでつぶやいたきりまとめてなかったネタ.

慶應の日吉キャンパスがある日吉駅.
日吉駅前には謎の銀色で球形のオブジェがあり,待ち合わせなどに利用されている.

ぎんたま

このオブジェを見るたびに,「これどう見てもリファレンス球だろ…」と思っていた.
リファレンス球というのは,映画などで実写にCG合成するときに使うものである.
CGを合成したいシーンに銀とか白の球を置いておいて,カメラで撮影する.
そうするとシーンの環境光の情報を手軽に取得できる.
そしてCGをレンダリングするときに環境光の情報を反映させてやれば,
そのシーンに馴染んだCG合成ができるというわけ.

普通はリファレンス球に映った画像を加工して利用するのであるが,
今回は日吉オブジェ(以下銀玉)の材質をそのままテクスチャとして適当なCGに貼りつける.
そうすると銀玉を好きな形に変形させるARができてしまう.

で,やってみたのがこちら↓
ティーポット

使ったのは例によってOpenCVとOpenGL.
OpenCVで画像中の球の部分をcv::getRectSubPixで切り取ってリサイズしておく.
まだ球の部分を指定するのは今は手動で行っているが,ハフ変換を使って自動化すると良いと思う.
OpenGLでその画像をテクスチャとして読み込んで,スフィアマッピングすれば完成.
スフィアマッピングのやり方は床井先生のページを参考に.
http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20050107

リファレンス球にするのは日吉の銀玉だけじゃなく,球形だったら何でも良い.
最近何かと話題の某テレビ局の丸いのをリファレンスにするとこんなこともできる.
たこ
8chだけにタコ?

この処理はリアルタイムに動作するので動画への適用も可能.
そのうち日吉に撮影に行って動画を作ろうと思う.

 

さて,昨日まではOpenGLでペンタブの入力を取得する方法について書いていたのだが,作りたいアプリの構成を考えるとOpenCV使ったほうが楽そうなので,OpenCVでも同様にbbTabletでペンタブ情報を取得してみた.

とりあえずglutのときと同じようにリンクしてコンパイルしてみると,盛大にエラーが出る.どうやらOpenCVのlibとbbTabletのlibが衝突しているらしい.ので,リンカの設定で「特定の規定のライブラリの無視」にLIBCMTDとmsvcprtdを追加すると,警告は出るものの,コンパイルは通る.

リンカの設定

で,位置と筆圧をゲットして線を引くだけのコードを書いてみた.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include "bbtablet.h"
#include "opencv2\\opencv.hpp"
 
#pragma comment(lib, "bbtabletds_vc10.lib")
#pragma comment(lib, "C:\\OpenCV2.2\\lib\\opencv_core220d.lib")
#pragma comment(lib, "C:\\OpenCV2.2\\lib\\opencv_highgui220d.lib")
 
using namespace cv;
 
#define WINDOW_NAME     "Tablet Test for OpenCV"
#define PEN_SIZE        20
#define TOUCH_THRESHOLD 0.1
 
int main(int argc, char *argv[])
{
    //ウィンドウ生成
    namedWindow(WINDOW_NAME, 1);
 
    //タブレットの初期化
    bbTabletEvent   tabletEvent;
    bbTabletDevice  &td = bbTabletDevice::getInstance( );
    HWND            hWnd = FindWindow(NULL, WINDOW_NAME);
    td.initTablet(hWnd, bbTabletDevice::SEPARATE_POINTER );
 
    //画像生成
    Mat image(480, 640, CV_8UC3, Scalar(255, 255, 255));
 
    Point pen, pen_prev;
 
    //メインループ
    while(1){
        while(td.getNextEvent(tabletEvent)){
            pen_prev = pen;
            pen.x = tabletEvent.getWinX();
            pen.y = tabletEvent.getWinY();
            float p = tabletEvent.pressure;
            if(p > TOUCH_THRESHOLD){
                line(image, pen_prev, pen, Scalar(0,0,0), (int)(PEN_SIZE*p), 8, 0);
            }
        }
 
        //ウィンドウに表示
        imshow(WINDOW_NAME, image);
 
        //Escキーで終了
        if(waitKey(1) == 27)break;
    }
 
    return 0;
}

実行結果はこんな感じ.

息子

結構綺麗に描けるもんだ.曲線補完とかアンチエイリアスとか掛けたくなるね.

 

 

© 2014 Saikoro Laboratory Blog Suffusion theme by Sayontan Sinha