プログラムについて:360度でとった画像を全天球画像として閲覧するプログラムを作りたい。
プログラムの主なアルゴリズム:表示画面のSizeと元画像のピクセルの座標変換を用いて実現させる。
現在の実行結果:
エラー出力(For文中での変数exの出力の例):
[ NaN, NaN, 0.0 ]
[ NaN, NaN, 0.0 ]
[ NaN, NaN, 0.0 ]
[ NaN, NaN, 0.0 ]
[ NaN, NaN, 0.0 ]
[ NaN, NaN, 0.0 .......
問題点:40行から3行ほどのコードが下のForループに入ると代入することなく勝手に代入される。
PVector ex= new PVector(sin(phi_v), -cos(phi_v), 0); PVector ey= new PVector(cos(theta_v)* cos(phi_v), cos(theta_v)* sin(phi_v), -sin(theta_v)); PVector ez= new PVector(sin(theta_v)* cos(phi_v), sin(theta_v)* sin(phi_v), cos(theta_v));
ピクセルで画像を正しく表示できない。
知りたいこと:どうして代入もしていない変数が勝手に値が変化するのか。
実現したいこと:画像を全天球画像で表示できるうえにプログラム自動で水平に移動するプログラム(水平な移動は今は特に問題ない。)
プロフラム
PImage
1PImage imgDst; 2 3float theta_v; 4float phi_v; 5float theta_fovx; 6 7 8void setup() { 9 size(640, 360); 10 frameRate(60); 11 12 imgSrc = loadImage("R0010014.JPG"); 13 imgDst = createImage(width, height, RGB); 14 15 theta_v = PI/2; // 2.3演 θ 16 phi_v = PI; // 2.4演 φ 17 theta_fovx = radians(50); // 50deg 18} 19 20void draw() { 21 22 // 以下 4行は様々な方向を見て動作を確認するための視線設定インタラクティブにする場合は削除する 23 final float PHI_PERIOD = 10 * 1000.0f; 24 final float THETA_PERIOD = 7 * 1000.0f; 25 phi_v = TWO_PI * millis() / PHI_PERIOD; 26 theta_v = HALF_PI + HALF_PI * sin(TWO_PI * millis() / THETA_PERIOD); 27 28 imgSrc.loadPixels(); 29 imgDst.loadPixels(); 30 31 float nx= imgDst.width, ny= imgDst.height; 32 // nx および ny はimgDst の幅および高さである. 33 34 float f=50; 35 float w= 2*f* tan(theta_fovx / 2); 36 float h= (ny/nx)*w; 37 // f の値は適当に決め,資料 2.2節からw と h を算出する. 38 39 PVector ex= new PVector(sin(phi_v), -cos(phi_v), 0); 40 PVector ey= new PVector(cos(theta_v)* cos(phi_v), cos(theta_v)* sin(phi_v), -sin(theta_v)); 41 PVector ez= new PVector(sin(theta_v)* cos(phi_v), sin(theta_v)* sin(phi_v), cos(theta_v)); 42 // println(ex, ey, ez); 43 // 視線方向 theta_v, phi_v から,カメラ座標系の基底ベクトルを算出する.(資料の 2.3) 44 // 基底ベクトルは 3本,各ベクトルは 3成分なので,float 型の変数 9 個を使うか, 45 //PVector クラスのインスタンスを 3 個使う. 46 47 48 for (int j = 0; j < imgDst.height; j++) { 49 for (int i = 0; i < imgDst.width; i++) { 50 // カメラ画像のあるピクセル (i,j)について考える 51 52 PVector c= new PVector( ((i- (nx/2))* (w/nx) ), ((j- (ny/2))* (h/ny) ), f); 53 // println(c); 54 // ピクセルの座標 (i,j)と,f,w,h を用いて,カメラ座標系におけるピクセルの 55 //3次元座標 (xc, yc, zc)を算出する.(資料の 2.2) 56 // PVector を使うなら,インスタンス 1 個で保持できる. 57 PVector v= new PVector(0, 0, 0); 58 PVector v1= ex; 59 //PVector v1= ex; 60 v1.mult(c.x); 61 PVector v2= new PVector(cos(theta_v)* cos(phi_v), cos(theta_v)* sin(phi_v), -sin(theta_v)); 62 v2.mult(c.y); 63 PVector v3= new PVector(sin(theta_v)* cos(phi_v), sin(theta_v)* sin(phi_v), cos(theta_v)); 64 v3.mult(c.z); 65 66 v.add(v1); 67 v.add(v2); 68 v.add(v3); 69 println(ex); 70 // println(ex, c.x, ex.mult(c.x)); 71 // カメラ座標系の基底ベクトルと,カメラ座標系におけるピクセルの 3次元座標 (xc, yc, zc)から, 72 // 全天球座標系において,原点からピクセルに向かうベクトルを算出する.(資料の 2.4の 3(b)) 73 float r= sqrt(v.x* v.x + v.y* v.y+ v.z* v.z); 74 float theta= atan(sqrt(v.x* v.x + v.y* v.y)/v.z); 75 //float theta= atan2(r, v.z); 76 float phi= atan(v.y/ v.x); 77 // float phi= atan2(v.x, v.y); 78 // ベクトルの成分から極座標に変換し (資料の 2),更にphi:0->2pi が画像の幅に, 79 // theta:0->pi が画像の高さになるようにスケール変換をすると, 80 // サンプリングすべき全天球画像の座標値 (x1,y1)が求まる. 81 // delay(1000); 82 83 84 int x1, y1; 85 // x1 = i; // これはとりあえず入れてるだけで,本来は x1 = (適切な計算式) 86 // y1 = j; // これはとりあえず入れてるだけで,本来は y1 = (適切な計算式) 87 88 x1= (int)(phi/(PI*2)); 89 y1= (int)(theta/(PI)); 90 // println(x1, y1); 91 // int x1= (int)c.x, y1= (int)c.y; 92 if (true) { 93 // println(x1 + y1 * imgSrc.width); 94 // (x1,y1)が画像内の座標であることを確認する. 95 // あるいは一段階前の theta, phi の時点で範囲内であることを確認してもよい. 96 // 範囲内であることを確認しないと,画像外にアクセスすることになり, 97 // プログラムの動作が停止する (エラーが出る)ので注意すること. 98 99 color co = imgSrc.pixels[x1 + y1 * imgSrc.width]; // 1節で説明した高品質化 (補間)をってもよい 100 imgDst.pixels[i + j * imgDst.width] = co; 101 } 102 } 103 } 104 imgDst.updatePixels(); 105 set(0, 0, imgDst); 106} 107
なかなかマイナな質問だと思います。お願いします。
更新補足:
今のところx1、y1の値は0です
float
1 float theta= atan(sqrt(v.x* v.x + v.y* v.y)/v.z); 2 //float theta= atan2(r, v.z); 3 float phi= atan(v.y/ v.x); 4コード
ここのphiとthetaはNANとなります。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。