added test for camera positions, slightly refactored the widgets

This commit is contained in:
Anatoly Baksheev 2014-01-10 00:31:27 +04:00
parent 8309d19f31
commit 462d516743
2 changed files with 110 additions and 105 deletions

View File

@ -622,29 +622,29 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect)
ConvertToVtkImage::convert(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<vtkImageFlip> flip_filter = vtkSmartPointer<vtkImageFlip>::New();
flip_filter->SetFilteredAxis(1); // Vertical flip
flip_filter->SetInputConnection(vtk_image->GetProducerPort());
flip_filter->Update();
// Scale the image based on the Rect
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->Scale(double(image.cols)/rect.width,double(image.rows)/rect.height,1.0);
transform->Scale(image.cols/(double)rect.width, image.rows/(double)rect.height, 1.0);
vtkSmartPointer<vtkImageReslice> image_reslice = vtkSmartPointer<vtkImageReslice>::New();
image_reslice->SetResliceTransform(transform);
image_reslice->SetInputConnection(flipFilter->GetOutputPort());
image_reslice->SetInputConnection(flip_filter->GetOutputPort());
image_reslice->SetOutputDimensionality(2);
image_reslice->InterpolateOn();
image_reslice->AutoCropOutputOn();
vtkSmartPointer<vtkImageMapper> imageMapper = vtkSmartPointer<vtkImageMapper>::New();
imageMapper->SetInputConnection(image_reslice->GetOutputPort());
imageMapper->SetColorWindow(255); // OpenCV color
imageMapper->SetColorLevel(127.5);
vtkSmartPointer<vtkImageMapper> image_mapper = vtkSmartPointer<vtkImageMapper>::New();
image_mapper->SetInputConnection(image_reslice->GetOutputPort());
image_mapper->SetColorWindow(255); // OpenCV color
image_mapper->SetColorLevel(127.5);
vtkSmartPointer<vtkActor2D> actor = vtkSmartPointer<vtkActor2D>::New();
actor->SetMapper(imageMapper);
actor->SetMapper(image_mapper);
actor->SetPosition(rect.x, rect.y);
WidgetAccessor::setProp(*this, actor);
@ -820,93 +820,6 @@ namespace cv { namespace viz { namespace
{
struct CameraPositionUtils
{
static void projectImage(double fovy, double far_end_height, const Mat &image,
double scale, const Color &color, vtkSmartPointer<vtkActor> actor)
{
// Create a camera
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
float aspect_ratio = float(image.cols)/float(image.rows);
// Create the vtk image
vtkSmartPointer<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
// Adjust a pixel of the vtk_image
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 0, color[2]);
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 1, color[1]);
vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 2, color[0]);
// 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();
Vec3d plane_center(0.0, 0.0, scale);
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]);
plane->SetNormal(0.0, 0.0, 1.0);
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->PreMultiply();
transform->Translate(plane_center[0], plane_center[1], plane_center[2]);
transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0);
transform->RotateY(180.0);
transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]);
// Apply the texture
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(flipFilter->GetOutputPort());
vtkSmartPointer<vtkTextureMapToPlane> texturePlane = vtkSmartPointer<vtkTextureMapToPlane>::New();
texturePlane->SetInputConnection(plane->GetOutputPort());
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transform_filter->SetTransform(transform);
transform_filter->SetInputConnection(texturePlane->GetOutputPort());
transform_filter->Update();
// Create frustum
camera->SetViewAngle(fovy);
camera->SetPosition(0.0, 0.0, 0.0);
camera->SetViewUp(0.0, 1.0, 0.0);
camera->SetFocalPoint(0.0, 0.0, 1.0);
camera->SetClippingRange(0.01, scale);
double planesArray[24];
camera->GetFrustumPlanes(aspect_ratio, planesArray);
vtkSmartPointer<vtkPlanes> planes = vtkSmartPointer<vtkPlanes>::New();
planes->SetFrustumPlanes(planesArray);
vtkSmartPointer<vtkFrustumSource> frustumSource =
vtkSmartPointer<vtkFrustumSource>::New();
frustumSource->SetPlanes(planes);
frustumSource->Update();
vtkSmartPointer<vtkExtractEdges> filter = vtkSmartPointer<vtkExtractEdges>::New();
filter->SetInputConnection(frustumSource->GetOutputPort());
filter->Update();
// Frustum needs to be textured or else it can't be combined with image
vtkSmartPointer<vtkTextureMapToPlane> frustum_texture = vtkSmartPointer<vtkTextureMapToPlane>::New();
frustum_texture->SetInputConnection(filter->GetOutputPort());
// Texture mapping with only one pixel from the image to have constant color
frustum_texture->SetSRange(0.0, 0.0);
frustum_texture->SetTRange(0.0, 0.0);
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
appendFilter->AddInputConnection(frustum_texture->GetOutputPort());
appendFilter->AddInputConnection(transform_filter->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> planeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
planeMapper->SetInputConnection(appendFilter->GetOutputPort());
actor->SetMapper(planeMapper);
actor->SetTexture(texture);
}
static vtkSmartPointer<vtkPolyData> createFrustum(double aspect_ratio, double fovy, double scale)
{
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
@ -916,11 +829,11 @@ namespace cv { namespace viz { namespace
camera->SetFocalPoint(0.0, 0.0, 1.0);
camera->SetClippingRange(1e-9, scale);
double planesArray[24];
camera->GetFrustumPlanes(aspect_ratio, planesArray);
double planes_array[24];
camera->GetFrustumPlanes(aspect_ratio, planes_array);
vtkSmartPointer<vtkPlanes> planes = vtkSmartPointer<vtkPlanes>::New();
planes->SetFrustumPlanes(planesArray);
planes->SetFrustumPlanes(planes_array);
vtkSmartPointer<vtkFrustumSource> frustumSource = vtkSmartPointer<vtkFrustumSource>::New();
frustumSource->SetPlanes(planes);
@ -932,6 +845,73 @@ namespace cv { namespace viz { namespace
return extract_edges->GetOutput();
}
static vtkSmartPointer<vtkActor> projectImage(double fovy, double far_end_height, const Mat &image, double scale, const Color &color)
{
float aspect_ratio = float(image.cols)/float(image.rows);
// Create the vtk image
vtkSmartPointer<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
// Adjust a pixel of the vtk_image
if(image.channels() == 1)
{
double gray = color[2] * 0.299 + color[1] * 0.578 + color[0] * 0.144;
vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, gray);
}
else
{
vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, color[2]);
vtk_image->SetScalarComponentFromDouble(0, 0, 0, 1, color[1]);
vtk_image->SetScalarComponentFromDouble(0, 0, 0, 2, color[0]);
}
Vec3d plane_center(0.0, 0.0, scale);
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
plane->SetCenter(plane_center.val);
plane->SetNormal(0.0, 0.0, 1.0);
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->PreMultiply();
transform->Translate(plane_center.val);
transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0);
transform->RotateY(180.0);
transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]);
// Apply the texture
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(vtk_image->GetProducerPort());
vtkSmartPointer<vtkTextureMapToPlane> texture_plane = vtkSmartPointer<vtkTextureMapToPlane>::New();
texture_plane->SetInputConnection(plane->GetOutputPort());
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transform_filter->SetInputConnection(texture_plane->GetOutputPort());
transform_filter->SetTransform(transform);
vtkSmartPointer<vtkPolyData> frustum = createFrustum(aspect_ratio, fovy, scale);
// Frustum needs to be textured or else it can't be combined with image
vtkSmartPointer<vtkTextureMapToPlane> frustum_texture = vtkSmartPointer<vtkTextureMapToPlane>::New();
frustum_texture->SetInputConnection(frustum->GetProducerPort());
// Texture mapping with only one pixel from the image to have constant color
frustum_texture->SetSRange(0.0, 0.0);
frustum_texture->SetTRange(0.0, 0.0);
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
appendFilter->AddInputConnection(frustum_texture->GetOutputPort());
appendFilter->AddInputConnection(transform_filter->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> planeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
planeMapper->SetInputConnection(appendFilter->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(planeMapper);
actor->SetTexture(texture);
return actor;
}
};
}}}
@ -994,8 +974,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, do
double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI;
double far_end_height = 2.00 * c_y * scale / f_y;
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor);
vtkSmartPointer<vtkActor> actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color);
WidgetAccessor::setProp(*this, actor);
}
@ -1005,8 +984,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, const Mat &image, do
double fovy = fov[1] * 180.0 / CV_PI;
double far_end_height = 2.0 * scale * tan(fov[1] * 0.5);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor);
vtkSmartPointer<vtkActor> actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color);
WidgetAccessor::setProp(*this, actor);
}

View File

@ -199,6 +199,33 @@ TEST(Viz, DISABLED_show_trajectory_reposition)
}
TEST(Viz, show_camera_positions)
{
Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png"));
Mat chs[3]; split(lena, chs);
Mat gray = 0.114 * chs[0] + 0.58 * chs[1] + 0.3 * chs[2];
Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0);
Affine3d poses[2];
for(int i = 0; i < 2; ++i)
{
Vec3d pose = 5 * Vec3d(sin(3.14 + 2.7 + i*60 * CV_PI/180), 0.4 - i*0.3, cos(3.14 + 2.7 + i*60 * CV_PI/180));
poses[i] = makeCameraPose(pose, Vec3d(0.0, 0.0, 0.0), Vec3d(0.0, -0.1, 0.0));
}
Viz3d viz("show_camera_positions");
viz.showWidget("sphe", WSphere(Point3d(0,0,0), 1.0));
viz.showWidget("coos", WCoordinateSystem(1.5));
viz.showWidget("pos1", WCameraPosition(0.75), poses[0]);
viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]);
viz.showWidget("pos3", WCameraPosition(0.75), poses[1]);
viz.showWidget("pos4", WCameraPosition(K, gray, 3, Color::indigo()), poses[1]);
viz.spin();
}
TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG)
{
Mesh mesh = Mesh::load(get_dragon_ply_file_path());