Hatena::ブログ(Diary)

colorcle

2011-07-28

KiRiE

| 16:47

iPad アプリを作ってみました.

切り絵アプリです.


審査に通ったようです.

現在 iTunes App Store で公開されています.

     iTunes App Store : KiRiE - 切り絵

有料ですがよろしければ,どうぞ.



f:id:colorcle:20110729191746p:image:w200:left

f:id:colorcle:20110729191747p:image:w200:left

2010-08-30

Shape from Silhouete 2

| 16:54

こないだのやつの

ちょっと解像度を上げて復元レベルも上げたやつ

f:id:colorcle:20100830163038g:image

結構ちゃんと復元してくれてるんだけど

なんかオブジェクトの端っこが消えてる

手とか足とか,尻尾なんかほとんどなくなっちゃった

原因としては元画像のカメラパラメータの推定がよくないのかも

カメラパラメータの情報がなかったので

こっちで勝手に推定というか目測というか適当に設定した

カメラパラメータの推定をどうやるのかってのがここからの問題


ソースも載せたいけど量が多い,あと自信ない

2次元描画系からだからね,なぜか

逆に考えればそれだけ更新できるってことでもあるけどね

幸いなことに他に書くこと無いからね

無更新記録更新のプレッシャーに耐えられなくなったら少しずつ載せます

2010-08-14

Shape from Silhouete

| 23:32

Visual Geometry Group Home Page

Dinosaur より...

f:id:colorcle:20100814231104g:image

レンダリングエンジンから自分で書いてみたりして

というか線を引くとこから多角形を塗りつぶすところから...

何やってんだか

2万ポリゴンくらいでやっぱりカクカク

でもまぁ全ての部分に自分の手が届くのがいいところ

あと自分の使いやすいように設計できるし〜

なんてね

Open CV くらいは使うべきか


ネタも無いくせにそれっぽく更新

何を言っても言い訳になるから何も言わないという言い訳

皆さん,暑いですがお変わりないでしょうか?

僕は良くも悪くも変わりません

停滞期.

多分,ここが大事!

なのですが

2010-05-03

PCAで3次元復元 2

| 00:19

ちょっと分かりかけてきた

こないだまずかったのは運動行列を正規化してなかったからだ

射影は多分あってた,正射影ってやつ


f:id:colorcle:20100430113930g:image:left

f:id:colorcle:20100504001805g:image


ちゃんと運動行列を正規化してみたのがこちら

なんとかできてるっぽい...かな?

ましにはなってるね


正規化するために行列ばっりいじくり回してた

ちょー疲れた

行と列がぐっちゃぐちゃさ

縦ベクトルとか横ベクトルとかぐっちゃぐちゃ

数学できないと目が回るね,まったく

一番簡単そうな正射影でこれだからね

やっと第一歩というところです

2010-04-30

PCAで3次元復元?

| 12:05

いやーさぼったさぼった

でもそんなにいつもいつも書くことあるってもんじゃないよね?

ただ書けばいいってもんじゃないよね?


今日はここの

点対応を用いた複数の2次元画像3次元形状復元-因子分解法の数理-

によると複数の2次元の対応点集合から3次元形状を復元できるらしい

正直数式は追いついてないですがどうやら因子分解によって2次元点集合の行列を

カメラの運動の行列と形状の行列に分解すればいいのだそうだ

そしてこれは主成分分析(特異値分解)して第3主成分までとればいいんだって

とりあえずやってみよう


3次元データは適当に検索して teapot にした

teapot obj - Google 検索

ファイル形式は OBJ 形式

まぁなんでもいいやね


んで読み込んでいくつか角度変えてそのまま2次元に落とす

今回は3枚の2次元点集合を使った

f:id:colorcle:20100430113924p:image:left

f:id:colorcle:20100430113925p:image:left

f:id:colorcle:20100430113926p:image:left






こんな感じ.

そしてこの3枚の2次元点集合を行列に突っ込んでPCAかけるだけ

かけた.かけました.

その結果がこれだ!

f:id:colorcle:20100430113930g:image:left

f:id:colorcle:20100430113931g:image


左がオリジナルのモデル.右が復元した3次元形状.

んーなんか変,ぼてっとなっとる

なんでやねん

あれかなー単純に2次元に落としたのがまずいのかな?

ちゃんと射影(投射?透視投影?)してあげなきゃダメなのかも?

まぁでもちゃんとできそうなことが分かったからこれからよく勉強しよう


実際に応用する際の問題点としては

全ての点の対応が分かってないといけないことと

全ての2次元画像に全ての点が含まれていないといけないこと

だから隠れ点は認められないし,各点の対応も自分で事前に見つけとかなきゃいけない

逆に言えばこの辺をどうにかできればカメラ画像から3次元形状を復元できるはず

なるほど


今回のソースはこちら.表示部分は省いとります.

あとPCAの部分とかは以前のを見てね.

//---------------------------------------------------------------------------
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <math.h>

using namespace std;

#include "pca.h"

//---------------------------------------------------------------------------
//teapot 読み込み
//---------------------------------------------------------------------------
void read_teapot(vector< vector<double> > &point,vector< vector<int> > &face)
{
    ifstream ifs("data/teapot.obj");
    string   line;
    stringstream ss;    
    
    if(!ifs) cout<<"file open error!"<<endl;
    
    while(getline(ifs,line)){
        ss.str(line);
        ss.clear(stringstream::goodbit);
        
        string flg;
        ss>>flg;
        
        if(flg=="v"){
            double         tmp;
            vector<double> p;
            
            while(ss>>tmp){
                p.push_back(tmp);
            }
            swap(p[1],p[2]);
            point.push_back(p);
        }
        else if(flg=="f"){
            int         tmp;
            vector<int> f;
            
            while(ss>>tmp){
                f.push_back(tmp-1);
            }
            face.push_back(f);
        }
    }    
}
//---------------------------------------------------------------------------
Matrix rmat_x(double a)
{
    Matrix r(4,4);
    
    r[0][0]=1;      r[0][1]=0;      r[0][2]=0;      r[0][3]=0;
    r[1][0]=0;      r[1][1]=cos(a); r[1][2]=sin(a); r[1][3]=0;
    r[2][0]=0;      r[2][1]=-sin(a);r[2][2]=cos(a); r[2][3]=0;
    r[3][0]=0;      r[3][1]=0;      r[3][2]=0;      r[3][3]=1;
    
    return r;
}
//---------------------------------------------------------------------------
Matrix rmat_y(double a)
{
    Matrix r(4,4);
    
    r[0][0]=cos(a); r[0][1]=0;      r[0][2]=-sin(a);r[0][3]=0;
    r[1][0]=0;      r[1][1]=1;      r[1][2]=0;      r[1][3]=0;
    r[2][0]=sin(a); r[2][1]=0;      r[2][2]=cos(a); r[2][3]=0;
    r[3][0]=0;      r[3][1]=0;      r[3][2]=0;      r[3][3]=1;
    
    return r;
}
//---------------------------------------------------------------------------
Matrix rmat_z(double a)
{
    Matrix r(4,4);
    
    r[0][0]=cos(a); r[0][1]=sin(a); r[0][2]=0;      r[0][3]=0;
    r[1][0]=-sin(a);r[1][1]=cos(a); r[1][2]=0;      r[1][3]=0;
    r[2][0]=0;      r[2][1]=0;      r[2][2]=1;      r[2][3]=0;
    r[3][0]=0;      r[3][1]=0;      r[3][2]=0;      r[3][3]=1;
    
    return r;
}
//---------------------------------------------------------------------------
int main()
{
    srand(time(NULL));
    
    vector< vector<double> > point;
    vector< vector<int> >    face;
    
    //teapot の3次元モデルを読み込み
    read_teapot(point,face);
    
    //Matrix に移し替える
    Matrix X(point.size(),4);
    for(int i=0;i<point.size();i++){
        for(int j=0;j<3;j++) X[i][j]=point[i][j];
        X[i][3]=1;
    }
    
    Matrix rx=rmat_x(90*M_PI/180);
    X=(rx*X.t()).t();
    
    int F=3;                    //復元に使用する2次元データ枚数
    int f=0;
    Matrix W(2*F,X.rdim());     //2次元データ集合の行列
    
    for(int i=0;i<360;i+=360/F){
        //適当に回転して
        rx=rmat_x(80*sin(i*M_PI/360)*M_PI/180);
        Matrix ry=rmat_y(i*M_PI/180);
        Matrix Y=(rx*ry*X.t()).t();
        
        //そのまま2次元に落とす,ノイズ付き
        for(int j=0;j<Y.rdim();j++){
            W[2*f+0][j]=Y[j][0]+(rand()%1000/10000.0-0.05);
            W[2*f+1][j]=Y[j][1]+(rand()%1000/10000.0-0.05);
        }
        f++;
    }
    
    //PCA
    Vector l;
    Matrix S=PCA::calc_pca(W,l);
    S=S.t();
    
    //復元結果
    Matrix V(S.rdim(),4);
    for(int i=0;i<S.rdim();i++){
        V[i][0]=S[i][0];
        V[i][1]=S[i][1];
        V[i][2]=S[i][2];
        V[i][3]=1;
    }
    
    cout<<"press enter>>";
    getchar();
    
    return 0;
}
//---------------------------------------------------------------------------