おまけ:RICOH THETAのJPG画像を平面-球変換してOpenGLで表示する
RICOHのTHETAが来たので、全方位画像をOpenGLで表示出来るようにしてみます。いつものように、openFrameworksのpointCloudExampleを改造して作ります。おそらく単純な極座標変換で大丈夫なので*1、画像座標を極座標(球面座標)値と見立てて、半径Rの球状の点群として3次元位置を計算しています。
#include "testApp.h"
#define _USE_MATH_DEFINES
#include <math.h>
//--------------------------------------------------------------
void testApp::setup() {
ofSetVerticalSync(true);
// load an image from disk
img.loadImage("R0010032.JPG");
// we're going to load a ton of points into an ofMesh
mesh.setMode(OF_PRIMITIVE_POINTS);
// loop through the image in the x and y axes
float r = 10.0f; // radius
for(int y = 0; y < (int)img.getHeight(); y++){
for(int x = 0; x < (int)img.getWidth(); x++){
ofColor cur = img.getColor(x, y);
cur.a = 255;
float theta = (float)y * M_PI / img.getHeight();
float phi = -(float)x * 2.0f * M_PI / img.getWidth();
float px = r * sin(theta) * cos(phi);
float py = r * sin(theta) * sin(phi);
float pz = r * cos(theta);
mesh.addColor(cur);
ofVec3f pos(px, py, pz);
mesh.addVertex(pos);
}
}
ofEnableDepthTest();
glEnable(GL_POINT_SMOOTH); // use circular points instead of square points
glPointSize(3); // make the points bigger
cam.setAutoDistance(false);
cam.setPosition(0,0,0);
cam.lookAt(ofVec3f(r,0,0),ofVec3f(0,0,1));
cam.setDistance(1.0);
}
//--------------------------------------------------------------
void testApp::update() {
}
//--------------------------------------------------------------
void testApp::draw() {
ofBackgroundGradient(ofColor::gray, ofColor::black, OF_GRADIENT_CIRCULAR);
// even points can overlap with each other, let's avoid that
cam.begin();
mesh.draw();
cam.end();
}
//--------------------------------------------------------------
void testApp::keyPressed(int key){
}
//--------------------------------------------------------------
void testApp::keyReleased(int key){
}
//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y){
}
//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::windowResized(int w, int h){
}
//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){
}
ファイル名を決めうちで与えていますが、引数渡しなどに適当に修正してください。ofxThreadedImageLoaderなどを利用すれば、URLからも画像を指定できるようになります。ほぼRICOH THETAの付属ビューアと同じことができますが、距離を遠くすると、裏側が見えるようになってしまうという制限があります。これを回避するには、球に法線を定義して、視線ベクトルと対抗しない面を表示しないようにしてやれば解決できます。OpenGLの関数では、
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
の2行を呼び出します。
fig.座標変換
THETA HACKが下記のページでまとめられています。
まだやられていないことをやろう。
http://blog.mobilehackerz.jp/2013/10/ricoh-thetahdriblimage-based-lighting.html
EXIF情報から加速度情報もとれるそうです。面白いなぁ。
http://d.hatena.ne.jp/xanxys/20131110/1384094832
RICOH デジタルカメラ RICOH THETA S 360°全天球イメージ撮影デバイス 910720
- 出版社/メーカー: リコー
- 発売日: 2015/10/30
- メディア: Camera
- この商品を含むブログ (1件) を見る
早くTheta Sを買わないと!時代に取り残される気がする。
*1:正距円筒座標とのこと