added test for camera positions, slightly refactored the widgets
This commit is contained in:
parent
8309d19f31
commit
462d516743
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
Loading…
x
Reference in New Issue
Block a user