image 3d widget with position, normal, up_vector

This commit is contained in:
ozantonkal 2013-07-22 17:18:19 +02:00
parent d0bd344a42
commit f9938da67d
2 changed files with 76 additions and 0 deletions

View File

@ -159,6 +159,7 @@ namespace cv
{
public:
Image3DWidget(const Mat &image, const Size &size);
Image3DWidget(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size);
void setImage(const Mat &image);

View File

@ -805,6 +805,81 @@ cv::viz::Image3DWidget::Image3DWidget(const Mat &image, const Size &size)
WidgetAccessor::setProp(*this, actor);
}
cv::viz::Image3DWidget::Image3DWidget(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size)
{
CV_Assert(!image.empty() && image.depth() == CV_8U);
// Create the vtk image and set its parameters based on input image
vtkSmartPointer<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
vtk_image->SetDimensions(image.cols, image.rows, 1);
vtk_image->SetNumberOfScalarComponents(image.channels());
vtk_image->SetScalarTypeToUnsignedChar();
vtk_image->AllocateScalars();
CopyImpl::copyImage(image, vtk_image);
// Need to flip the image as the coordinates are different in OpenCV and VTK
vtkSmartPointer<vtkImageFlip> flipFilter = vtkSmartPointer<vtkImageFlip>::New();
flipFilter->SetFilteredAxis(1); // Vertical flip
flipFilter->SetInputConnection(vtk_image->GetProducerPort());
flipFilter->Update();
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
plane->SetCenter(0.0, 0.0, 0.0);
plane->SetNormal(0.0, 0.0, 1.0);
// Compute the transformation matrix for drawing the camera frame in a scene
Vec3f u,v,n;
n = normalize(normal);
u = normalize(up_vector.cross(n));
v = n.cross(u);
vtkSmartPointer<vtkMatrix4x4> mat_trans = vtkSmartPointer<vtkMatrix4x4>::New();
mat_trans->SetElement(0,0,u[0]);
mat_trans->SetElement(0,1,u[1]);
mat_trans->SetElement(0,2,u[2]);
mat_trans->SetElement(1,0,v[0]);
mat_trans->SetElement(1,1,v[1]);
mat_trans->SetElement(1,2,v[2]);
mat_trans->SetElement(2,0,n[0]);
mat_trans->SetElement(2,1,n[1]);
mat_trans->SetElement(2,2,n[2]);
// Inverse rotation (orthogonal, so just take transpose)
mat_trans->Transpose();
// Then translate the coordinate frame to camera position
mat_trans->SetElement(0,3,position[0]);
mat_trans->SetElement(1,3,position[1]);
mat_trans->SetElement(2,3,position[2]);
mat_trans->SetElement(3,3,1);
// Apply the texture
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(flipFilter->GetOutputPort());
vtkSmartPointer<vtkTextureMapToPlane> texturePlane = vtkSmartPointer<vtkTextureMapToPlane>::New();
texturePlane->SetInputConnection(plane->GetOutputPort());
// Apply the transform after texture mapping
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->PreMultiply();
transform->SetMatrix(mat_trans);
transform->Scale(size.width, size.height, 1.0);
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transform_filter->SetTransform(transform);
transform_filter->SetInputConnection(texturePlane->GetOutputPort());
transform_filter->Update();
vtkSmartPointer<vtkPolyDataMapper> planeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
planeMapper->SetInputConnection(transform_filter->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(planeMapper);
actor->SetTexture(texture);
WidgetAccessor::setProp(*this, actor);
}
void cv::viz::Image3DWidget::setImage(const Mat &image)
{
CV_Assert(!image.empty() && image.depth() == CV_8U);