キスミントとドロネー三角形分割with openCV

今回キスミントの新宿でのイベントで,システムと映像エフェクトをピチャピチャつくりましたーかなりおもしろい感じになりましたねー

裏からデコへのプロジェクションが一台と,正面から顔へのプロジェクション一台.中で人が口を動かしてます!!

自由廊JIROさん作でかい顔.上半分がFRPで下がシリコン



社長体験中!こんな感じでプリクラみたいに顔撮影して..



撮影したら顔がでかでかと映し出されて..



噛んだ瞬間このへんBAAAAAANGでエフェクトがかかり..



今回のディレクションはDGNのたかしさん


今回,エフェクトを10種類つくったけど,その中でも一番頑張ったのは,ガラスが割れるエフェクト.むむーんと思い,結局,顔の領域をドロネー三角形で分割してそれにテクスチャ張りつつ落としたんですが..
なかなかめんどくさかっし,openCVのドロネー三角形からそれぞれの三角形を取り出しかたがわからんという書き込みばっかだったから,僕のごりおし方法を披露します.基本開発はopenframeworksつかってるからofなんちゃらは無視して大丈夫です.なかなかそれっぽく見えましたぜよ!







と,思ったけど,どたばたソースだから何をやったか忘れてしまった..
確か,ある辺の右回りと左回りの三角形をみて,頂点が一致してなかったら三角形をvectorに追加してった気がします.
いらないとこはちょっと消したけど,このソースでわかる人いるかな..
わからなかったら連絡ください.一緒に勉強しましょう..w

こいつでsubdivをつくって..

CvSubdiv2D* btTriangleDivision::init_delaunay( CvMemStorage* storage,
CvRect rect )
{

CvSubdiv2D* subdiv;

subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*subdiv),
sizeof(CvSubdiv2DPoint),
sizeof(CvQuadEdge2D),
storage );
cvInitSubdivDelaunay2D( subdiv, rect );

return subdiv;

}

こいつにぶちこんで三角形のベクターをゲット

void btTriangleDivision::getTriangles(CvSubdiv2D* subdiv){

CvSeqReader reader;
int i, total = subdiv->edges->total;
int elem_size = subdiv->edges->elem_size;

cvStartReadSeq( (CvSeq*)(subdiv->edges), &reader, 0 );

int tID = 0;

for( i = 0; i < total; i++ ) { CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr); if( CV_IS_SET_ELEM(edge)) { ofxVec3f color; bool isTriangle = true; TriangleParameter triangleParameter[3]; color.x = 255; color.y = 0; color.z = 0; triangleParameter[0] = draw_subdiv_edge((CvSubdiv2DEdge)edge, color, 0); color.x = 2; color.y = 0; color.z = 255; triangleParameter[1] = draw_subdiv_edge(cvSubdiv2DGetEdge((CvSubdiv2DEdge)edge, CV_NEXT_AROUND_LEFT ), color, 1); isTriangle = triangleParameter[0].isTriangle * triangleParameter[1].isTriangle * triangleParameter[1].isTriangle; if(isTriangle){ btTriangle newTriangle; triangles.push_back(newTriangle); tID ++; } //double color.x = 255; color.y = 0; color.z = 0; triangleParameter[0] = draw_subdiv_edge((CvSubdiv2DEdge)edge, color, 0); color.x = 2; color.y = 255; color.z = 25; triangleParameter[2] = draw_subdiv_edge(cvSubdiv2DGetEdge((CvSubdiv2DEdge)edge, CV_NEXT_AROUND_RIGHT), color, 2); isTriangle = triangleParameter[0].isTriangle * triangleParameter[2].isTriangle * triangleParameter[2].isTriangle; if(isTriangle){ if(triangleParameter[2].posS != triangles[tID - 1].point[2]){ btTriangle newTriangle; newTriangle.ID = tID; triangles.push_back(newTriangle); tID ++; } } //finish double } CV_NEXT_SEQ_ELEM( elem_size, reader ); } } TriangleParameter btTriangleDivision::draw_subdiv_edge(CvSubdiv2DEdge edge, ofxVec3f color , int edgeID) { CvSubdiv2DPoint* org_pt; CvSubdiv2DPoint* dst_pt; CvPoint2D32f org; CvPoint2D32f dst; CvPoint iorg, idst; org_pt = cvSubdiv2DEdgeOrg(edge); dst_pt = cvSubdiv2DEdgeDst(edge); TriangleParameter triangleParameter; triangleParameter.isTriangle = true; if( org_pt && dst_pt && org_pt->pt.x > 0 && dst_pt->pt.y > 0 && org_pt->pt.x < w && dst_pt->pt.y < h ) { org = org_pt->pt;
dst = dst_pt->pt;

triangleParameter.posS.x = org_pt->pt.x;
triangleParameter.posS.y = org_pt->pt.y;
triangleParameter.posD.x = dst_pt->pt.x;
triangleParameter.posD.y = dst_pt->pt.y;

iorg = cvPoint( cvRound( org.x ), cvRound( org.y ));
idst = cvPoint( cvRound( dst.x ), cvRound( dst.y ));
ofSetColor(color.x, color.y, color.z);
// ofLine(iorg.x, iorg.y, idst.x, idst.y);
ofSetColor(255, 0, 0, 100);
ofNoFill();
//ofCircle(iorg.x, iorg.y, 5);
ofSetColor(2, 255, 0, 100);
//ofCircle(idst.x, idst.y, 5);
ofFill();
}else{
triangleParameter.isTriangle = false;
}
return triangleParameter;
}

Tags: , , ,