2010年12月19日日曜日

Bezier曲線

OpenGLで曲面を描画する方法について調べている。
その中でベジエ曲線とかB-splite曲線とかいろいろ出てきた。

文章や図を眺めてるだけだけじゃイマイチ理解が深まらないので、Procceing上でベジエ曲線描画するプログラムを自力実装してみた(注:Processingにはベジエ曲線を描画するための関数、bezier()があるので純粋に描画したいだけならそれ使った方が早いです)。


int w = 500;
int h = 500;

void setup(){
smooth();
noStroke();
fill(200,0,0,200);
size(w,h);
float[][] pArray ={{50.,200.},
{200.,100.},
{300.,400.},
{450.,200.}};
fill(0,200,0,200);
Bezier(pArray);


fill(200,0,0,200);
for(int i = 0;i < pArray.length;i++){
ellipse(pArray[i][0],pArray[i][1],10,10);
}
}

void draw(){
}

int combination(int n,int k){
int c = 0;

c = factorial(n) / (factorial(k) * factorial(n - k));

return c;
}

int factorial(int n){

if(n == 0){
return 1;
}

int f = 0;

if(n == 1){
return n;
}
else{
f = n * factorial(n - 1);
}
return f;
}

float Berstein(int i,int N,float t){
float b = 0;
b = combination(N,i) * pow((1 - t),(N - i)) * pow(t,i);
return b;
}

void Bezier(float[][] pArray){
final int numT = 1000;
final int x = 0;
final int y = 1;

for(int ti = 0;ti <= numT;ti++){
float t = ti / float(numT);
float px = 0;
float py = 0;
for(int i = 0;i < pArray.length;i++){
float b = Berstein(i,pArray.length - 1,t);
px += b * pArray[i][x];
py += b * pArray[i][y];
}
ellipse(px,py,10,10);
}
}


出力結果はこんな感じ。

2010年12月15日水曜日

OpenGLのキーボード入力

OpenGL触ってて、色々と引っかかったのでメモ。

・OpenGLで矢印とかファンクションキーから入力を受け付けたい場合は、glutSpecialFunc()に特殊キーのコールバック関数を設定する必要がある(C++の場合。Pythonの場合は特殊キーがどうとか考えなくてOK←追記:PyQtでOpenGLウィジェットを用いる場合の話です。OpenGL単体で使う場合は必要)。

※こんな感じ

void specialKeyFunc(unsigned char key,int x,int y){
if(key == GLUT_KEY_LEFT){
//process
}
else if(key == GLUT_KEY_RIGHT) {
//process
}
}

glutSpecialFunc(specialKeyFunc);


・文字を描画する際にはglutBitmapCharacter()を利用する(ココとかココを参考に)。

2010年12月13日月曜日

続OpenCV(光学迷彩的な何か

引き続きOpenCV。
光学迷彩的な何かを作ってみた。

やってることは至極単純で、事前に撮影した室内の画像とwebカムからキャプチャした画像の差分を計算しているだけ。


↑こんなん。左上が処理後、右上がキャプチャ画像、左下がもとの背景画像。
デコ部分の処理が甘く浮き上がってしまっている…。


それにしても、1000円かそこらのwebカムと無料のソフトウェアライブラリでここまで遊べるとは…。
引き続きいろいろ試してみたい所存でございます。

2010年12月12日日曜日

OpenCVが楽しすぎる件について

C++の勉強がてらOpenCVを触っているんだけど、これがかなり楽しい。

とりあえず、Webカムからリアルタイムに画像取得→画像から顔認識して顔部分の色を変化させる、くらいまでは簡単に出来た。




※左がカメラキャプチャした元画像、右が顔認識した部分の色を変化させたもの


一応下に使用したC++のソースを載せておく。


#include <cv.h>
#include <highgui.h>
#include <ctype.h>

int main (int argc, char **argv)
{
CvCapture *capture = 0;
IplImage *frame = 0;
IplImage *out = 0;
double w = 320, h = 240;
int c;

if (argc == 1 || (argc == 2 && strlen (argv[1]) == 1 && isdigit (argv[1][0])))
capture = cvCreateCameraCapture (argc == 2 ? argv[1][0] - '0' : 0);

cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH, w);
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_HEIGHT, h);

CvHaarClassifierCascade* cascade = cvLoadHaarClassifierCascade( "C:/OpenCV2.0/data/haarcascades/haarcascade_frontalface_default.xml",cvSize(1,1));
CvMemStorage* storage = cvCreateMemStorage(0);

cvNamedWindow ("Capture", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Face detection", CV_WINDOW_AUTOSIZE);
while (1) {
frame = cvQueryFrame (capture);
cvShowImage ("Capture", frame);

out = frame;

CvSeq* objects = cvHaarDetectObjects(
frame,
cascade,
storage,
1.1,
2,
0,
cvSize(30,30));

for(int i = 0;i < (objects ? objects->total : 0);i++){
CvRect* r = (CvRect*) cvGetSeqElem(objects,i);
cvSetImageROI(out,cvRect(r->x,r->y,r->width,r->height));
cvAddS(out,cvScalar(200),out);
cvResetImageROI(out);
}

cvShowImage("Face detection",out);

c = cvWaitKey (2);
if (c == '\x1b')
break;
}

cvReleaseCapture (&capture);
cvDestroyWindow ("Capture");
cvDestroyWindow ("Face detection");

return 0;
}



※おまけ


お約束。

EclipseとCDTとPythonとOpenCVとわた(ry

今日も引き続きEclipseの環境構築。

OpenCVなぞをインストールしていた。

手順に関してはココを参考にしておけば間違いない。

とにかく問題になったのはOpenCVの最新バージョン2.2をインストールしてしまったこと。
上記サイトでは2.0をインストールしていて、そのとおりにやってみると確かに動く。

これが2.2をインストールしてしまうと、CDTでもPythonでも動かなかった(少なくとも自分の使っているマシンでは)…。

ソフトウェアモジュールはできるだけ安定して動くバージョンをインストールしよう、というお話。

2010年12月11日土曜日

EclipseとCDTとOpenGLと私

Eclipse+CDT+OpenGLメモ

・glutの設定はココに書いてある通り行うべし
・OpenGLプログラムを作成する際、描画関数内で頂点情報を指定したあと、swapBufferes()を忘れずに記述すること
※2010/12/12/追記:swapBuffers()は無くてもOK