初音ミクさんをOpenCV上に召喚(仮)する(OpenCV 3.0.0-dev vizを使ってみる)
OpenCV 3.0.0からサポートしているvizモジュールを使ってみたよ!使ってみたけど、OpenCVとの関係性が全くないよ!釣記事だね!(嘘)
1.vizモジュールをinstallする
apt-get install libvtk5.8* でとにかく何でもかんでも入れて、cmakeしなおす。
- OpenCV modules: -- To be built: core flann imgproc highgui features2d calib3d cudaarithm ml nonfree objdetect video contrib cudawarping cuda cudafilters cudaimgproc legacy cudabgsegm cudacodec cudafeatures2d cudaoptflow cudastereo optim photo shape softcascade stitching superres ts videostab viz -- Disabled: world -- Disabled by dependency: - -- Unavailable: androidcamera cudalegacy cudev java matlab python -- -- GUI: -- QT: NO -- GTK+ 2.x: YES (ver 2.24.20) -- GThread : YES (ver 2.38.1) -- GtkGlExt: NO -- OpenGL support: NO -- VTK support: YES (ver 5.8.0)
なって、VTKが有効になる。
2.ミクさんを用意する
今回は、なんとなーく(点数が少ない方が楽なので)こちらのミクさんを。
http://tawaship.blog134.fc2.com/blog-entry-69.html#more
3.ミクさんをバラバラにする
バイナリフォーマットは、このあたりを参考にして、C言語(≠C++)で分解。
音がなるので要注意っと。
4. VTKにぶちこむ
点情報をこうやってぶちこんだり
points->InsertNextPoint(v.vertex[i].pos.x,
v.vertex[i].pos.y,
v.vertex[i].pos.z);
面情報をこうやってぶちこんだり
vtkSmartPointer < vtkTriangle > triangle = vtkSmartPointer < vtkTriangle >::New();
triangle->GetPointIds()->SetId(0, f.face_vert_index[i]);
triangle->GetPointIds()->SetId(1,f.face_vert_index[i + 1]);
triangle->GetPointIds()->SetId(2,f.face_vert_index[i + 2]);
cells->InsertNextCell(triangle);
多分、材質情報を読み込んだり、色を変えたりするともっとそれらしくなるだろうけど、とりあえず”3D表示する"までできたので、満足してみる。
追記: Lat式ミクVer 2.31さん ( http://bowlroll.net/up/dl30199 ) もこの通り
a.out : a.cpp
g++ \
-g \
-O2 \
-std=gnu++11 \
-Wno-deprecated \
-Wno-unused-result \
a.cpp \
-lvtkRendering -lvtkGraphics -lvtkIO -lvtkFiltering \
-lvtkCommon -lvtksys -lpthread -lm\
`pkg-config opencv --cflags --libs` \
-I/usr/include/vtk-5.8/
a.cpp
#include <cstdio>
#include <cstdint>
#include <iostream>
#include <opencv/cv.hpp>
#include <opencv2/viz.hpp>
#include <opencv2/viz/widget_accessor.hpp>
#include <vtkPoints.h>
#include <vtkTriangle.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkIdList.h>
#include <vtkActor.h>
#include <vtkProp.h>
using namespace cv;
using namespace std;
class PMD:public viz::Widget3D {
private:
struct PMDHeader {
uint8_t ID[3];
float Version;
uint8_t ModelName[20];
uint8_t Comment[256];
} __attribute__ *1;
struct x_Vector {
float x;
float y;
float z;
} __attribute__ *2;
struct x_Coords2d {
float u;
float v;
} __attribute__ *3;
struct PMD_vertex {
x_Vector pos;
x_Vector normal;
x_Coords2d uv;
uint16_t bone_num[2];
uint8_t bone_weight;
uint8_t edge_flag;
} __attribute__ *4;
struct PMDVertexList {
uint32_t vert_count;
PMD_vertex *vertex;
} __attribute__ *5;
struct PMDFaceList {
uint32_t face_vert_count;
uint16_t *face_vert_index;
} __attribute__ *6;
PMDHeader h;
PMDVertexList v;
PMDFaceList f;
public:
PMD(char *fname) {
FILE *fp = fopen(fname, "r");
vtkSmartPointer < vtkPoints > points =
vtkSmartPointer < vtkPoints >::New();
vtkSmartPointer < vtkCellArray > cells =
vtkSmartPointer < vtkCellArray >::New();
{ // Header
fread(&h, sizeof(h), 1, fp);
printf("%c%c%c\n", h.ID[0], h.ID[1], h.ID[2]);
printf("%f\n", h.Version);
}
{ // Vertex
fread(&v.vert_count, sizeof(uint32_t), 1, fp);
printf("vertexs = %d\n", v.vert_count);
v.vertex =
(PMD_vertex *) malloc(sizeof(PMD_vertex) * v.vert_count);
for (int i = 0; i < v.vert_count; i++) {
fread(&v.vertex[i].pos.x, sizeof(float), 1, fp);
fread(&v.vertex[i].pos.y, sizeof(float), 1, fp);
fread(&v.vertex[i].pos.z, sizeof(float), 1, fp);
fread(&v.vertex[i].normal.x, sizeof(float), 1, fp);
fread(&v.vertex[i].normal.y, sizeof(float), 1, fp);
fread(&v.vertex[i].normal.z, sizeof(float), 1, fp);
fread(&v.vertex[i].uv.u, sizeof(float), 1, fp);
fread(&v.vertex[i].uv.v, sizeof(float), 1, fp);
fread(&v.vertex[i].bone_num[0], sizeof(uint16_t), 1, fp);
fread(&v.vertex[i].bone_num[1], sizeof(uint16_t), 1, fp);
fread(&v.vertex[i].bone_weight, sizeof(uint8_t), 1, fp);
fread(&v.vertex[i].edge_flag, sizeof(uint8_t), 1, fp);
points->InsertNextPoint(v.vertex[i].pos.x,
v.vertex[i].pos.y,
v.vertex[i].pos.z);
}
}
{ // faces
fread(&f.face_vert_count, sizeof(uint32_t), 1, fp);
printf("faces = %d\n", f.face_vert_count);
f.face_vert_index =
(uint16_t *) malloc(sizeof(uint16_t) * f.face_vert_count);
for (int i = 0; i < f.face_vert_count; i++) {
fread(&f.face_vert_index[i], sizeof(uint16_t), 1, fp);
}
for (int i = 0; i < f.face_vert_count; i += 3) {
vtkSmartPointer < vtkTriangle > triangle =
vtkSmartPointer < vtkTriangle >::New();
triangle->GetPointIds()->SetId(0, f.face_vert_index[i]);
triangle->GetPointIds()->SetId(1,
f.face_vert_index[i + 1]);
triangle->GetPointIds()->SetId(2,
f.face_vert_index[i + 2]);
cells->InsertNextCell(triangle);
}
}
fclose(fp);
// Create a polydata object
vtkSmartPointer < vtkPolyData > polyData =
vtkSmartPointer < vtkPolyData >::New();
// Add the geometry and topology to the polydata
polyData->SetPoints(points);
polyData->SetPolys(cells);
// Create mapper and actor
vtkSmartPointer < vtkPolyDataMapper > mapper =
vtkSmartPointer < vtkPolyDataMapper >::New();
#if VTK_MAJOR_VERSION <= 5
mapper->SetInput(polyData);
#else
mapper->SetInputData(polyData);
#endif
vtkSmartPointer < vtkActor > actor =
vtkSmartPointer < vtkActor >::New();
actor->SetMapper(mapper);
// Store this actor in the widget in order that visualizer can access it
viz::WidgetAccessor::setProp(*this, actor);
// Set the color of the widget. This has to be called after WidgetAccessor.
setColor(viz::Color::red());
}
~PMD() {
// Leaked ...
}
};
int main()
{
char filename[] = "CHANxCO_style_MIKU.pmd";
PMD *dat = new PMD(filename);
viz::Viz3d myWindow("Viz Demo");
myWindow.showWidget("TRIANGLE", *dat);
myWindow.spin();
return 0;
}