diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 425502d641..3b4e3619da 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -125,6 +125,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ @@ -137,6 +138,7 @@ #include #include #include +#include #include #include diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 422ea9be33..6f4392b0fd 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -617,15 +617,13 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) { CV_Assert(!image.empty() && image.depth() == CV_8U); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flip_filter = vtkSmartPointer::New(); flip_filter->SetFilteredAxis(1); // Vertical flip - flip_filter->SetInputConnection(vtk_image->GetProducerPort()); - flip_filter->Update(); + flip_filter->SetInputConnection(source->GetOutputPort()); // Scale the image based on the Rect vtkSmartPointer transform = vtkSmartPointer::New(); @@ -637,6 +635,7 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) image_reslice->SetOutputDimensionality(2); image_reslice->InterpolateOn(); image_reslice->AutoCropOutputOn(); + image_reslice->Update(); vtkSmartPointer image_mapper = vtkSmartPointer::New(); image_mapper->SetInputConnection(image_reslice->GetOutputPort()); @@ -661,13 +660,13 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) CV_Assert("This widget does not support overlay image." && mapper); // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); mapper->SetInputConnection(flipFilter->GetOutputPort()); @@ -686,14 +685,13 @@ cv::viz::WImage3D::WImage3D(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 vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); Vec3d plane_center(size.width * 0.5, size.height * 0.5, 0.0); @@ -735,13 +733,13 @@ cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Ve CV_Assert(!image.empty() && image.depth() == CV_8U); // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); vtkSmartPointer plane = vtkSmartPointer::New(); @@ -790,14 +788,13 @@ void cv::viz::WImage3D::setImage(const Mat &image) vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("This widget does not support 3D image." && actor); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); // Apply the texture @@ -850,8 +847,10 @@ namespace cv { namespace viz { namespace float aspect_ratio = float(image.cols)/float(image.rows); // Create the vtk image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); + source->Update(); + vtkSmartPointer vtk_image = source->GetOutput(); // Adjust a pixel of the vtk_image if(image.channels() == 1) diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 03d5c0325e..f9ccf09448 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -179,67 +179,4 @@ private: bool removeActorFromRenderer(const vtkSmartPointer &actor); }; -namespace cv -{ - namespace viz - { - struct color_tag {}; - struct gray_tag {}; - - inline Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } - inline Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } - - struct ConvertToVtkImage - { - struct Impl - { - typedef unsigned char uchar; - - static void copyImage(const Mat &source, vtkSmartPointer output, color_tag tag) - { - for (int y = 0; y < source.rows; ++y) - { - const uchar *srow = source.ptr(y); - for (int x = 0; x < source.cols; ++x, srow += source.channels()) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = fetchRgb(srow, tag); - } - output->Modified(); - } - - static void copyImage(const Mat &source, vtkSmartPointer output, gray_tag) - { - for (int y = 0; y < source.rows; ++y) - { - const uchar *srow = source.ptr(y); - for (int x = 0; x < source.cols; ++x) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; - } - output->Modified(); - } - }; - - static void convert(const Mat &image, vtkSmartPointer output) - { - // Create the vtk image - output->SetDimensions(image.cols, image.rows, 1); -#if VTK_MAJOR_VERSION <= 5 - output->SetNumberOfScalarComponents(image.channels()); - output->SetScalarTypeToUnsignedChar(); - output->AllocateScalars(); -#else - output->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); -#endif - switch(image.channels()) - { - case 1: Impl::copyImage(image, output, gray_tag()); break; - case 3: - case 4: Impl::copyImage(image, output, color_tag()); break; - default: - CV_Assert(!"Unsupported channel number"); - } - } - }; - } -} - #endif diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index 1d299f47ce..69262f247a 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -56,7 +56,7 @@ namespace cv { public: static vtkCloudMatSink *New(); - vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter); + vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 00e6adf1ee..a7f9fff89a 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -59,7 +59,7 @@ namespace cv { public: static vtkCloudMatSource *New(); - vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); + vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm) virtual int SetCloud(InputArray cloud); virtual int SetColorCloud(InputArray cloud, InputArray colors = noArray()); diff --git a/modules/viz/src/vtk/vtkImageMatSource.cpp b/modules/viz/src/vtk/vtkImageMatSource.cpp new file mode 100644 index 0000000000..2147039d71 --- /dev/null +++ b/modules/viz/src/vtk/vtkImageMatSource.cpp @@ -0,0 +1,140 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkImageMatSource); +}} + +cv::viz::vtkImageMatSource::vtkImageMatSource() +{ + this->SetNumberOfInputPorts(0); + this->ImageData = vtkImageData::New(); +} + +int cv::viz::vtkImageMatSource::RequestInformation(vtkInformation *, vtkInformationVector**, vtkInformationVector *outputVector) +{ + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->ImageData->GetExtent(), 6); + outInfo->Set(vtkDataObject::SPACING(), 1.0, 1.0, 1.0); + outInfo->Set(vtkDataObject::ORIGIN(), 0.0, 0.0, 0.0); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->ImageData->GetScalarType(), this->ImageData->GetNumberOfScalarComponents()); + return 1; +} + +int cv::viz::vtkImageMatSource::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *output = vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + output->ShallowCopy(this->ImageData); + return 1; +} + +void cv::viz::vtkImageMatSource::SetImage(InputArray _image) +{ + CV_Assert(_image.depth() == CV_8U && _image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4); + + Mat image = _image.getMat(); + + this->ImageData->SetDimensions(image.cols, image.rows, 1); +#if VTK_MAJOR_VERSION <= 5 + this->ImageData->SetNumberOfScalarComponents(std::min(3, image.channels())); + this->ImageData->SetScalarTypeToUnsignedChar(); + this->ImageData->AllocateScalars(); +#else + this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, std::min(3, image.channels())); +#endif + + switch(image.channels()) + { + case 1: copyGrayImage(image, this->ImageData); + case 3: copyRGBImage (image, this->ImageData); + case 4: copyRGBAImage(image, this->ImageData); + } + this->ImageData->Modified(); +} + +void cv::viz::vtkImageMatSource::copyGrayImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; + } +} + +void cv::viz::vtkImageMatSource::copyRGBImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x, srow += source.channels()) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec3b(srow[2], srow[1], srow[0]); + } +} + +void cv::viz::vtkImageMatSource::copyRGBAImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x, srow += source.channels()) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec4b(srow[2], srow[1], srow[0], srow[3]); + } +} diff --git a/modules/viz/src/vtk/vtkImageMatSource.h b/modules/viz/src/vtk/vtkImageMatSource.h new file mode 100644 index 0000000000..a4340346c1 --- /dev/null +++ b/modules/viz/src/vtk/vtkImageMatSource.h @@ -0,0 +1,84 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +#ifndef __vtkImageMatSource_h +#define __vtkImageMatSource_h + +namespace cv +{ + namespace viz + { + class vtkImageMatSource : public vtkImageAlgorithm + { + public: + static vtkImageMatSource *New(); + vtkTypeMacro(vtkImageMatSource,vtkImageAlgorithm); + + void SetImage(InputArray image); + + protected: + vtkImageMatSource(); + ~vtkImageMatSource() {} + + vtkSmartPointer ImageData; + + int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*); + int RequestData (vtkInformation*, vtkInformationVector**, vtkInformationVector*); + private: + vtkImageMatSource(const vtkImageMatSource&); // Not implemented. + void operator=(const vtkImageMatSource&); // Not implemented. + + static void copyGrayImage(const Mat &source, vtkSmartPointer output); + static void copyRGBImage (const Mat &source, vtkSmartPointer output); + static void copyRGBAImage(const Mat &source, vtkSmartPointer output); + }; + } +} + + +#endif + + diff --git a/modules/viz/src/vtk/vtkOBJWriter.h b/modules/viz/src/vtk/vtkOBJWriter.h index 9bf5403e43..f8889884d7 100644 --- a/modules/viz/src/vtk/vtkOBJWriter.h +++ b/modules/viz/src/vtk/vtkOBJWriter.h @@ -55,7 +55,7 @@ namespace cv { public: static vtkOBJWriter *New(); - vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter); + vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); vtkGetMacro(DecimalPrecision, int); diff --git a/modules/viz/src/vtk/vtkTrajectorySource.h b/modules/viz/src/vtk/vtkTrajectorySource.h index 9182509653..f6c9c77b9c 100644 --- a/modules/viz/src/vtk/vtkTrajectorySource.h +++ b/modules/viz/src/vtk/vtkTrajectorySource.h @@ -59,7 +59,7 @@ namespace cv { public: static vtkTrajectorySource *New(); - vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm); + vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm) virtual void SetTrajectory(InputArray trajectory); diff --git a/modules/viz/src/vtk/vtkXYZWriter.h b/modules/viz/src/vtk/vtkXYZWriter.h index bc49d10ef1..3db18b793b 100644 --- a/modules/viz/src/vtk/vtkXYZWriter.h +++ b/modules/viz/src/vtk/vtkXYZWriter.h @@ -55,11 +55,11 @@ namespace cv { public: static vtkXYZWriter *New(); - vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter); + vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); - vtkGetMacro(DecimalPrecision, int); - vtkSetMacro(DecimalPrecision, int); + vtkGetMacro(DecimalPrecision, int) + vtkSetMacro(DecimalPrecision, int) protected: vtkXYZWriter(); diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index e4fe78420c..1a5c4fe1cc 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -93,6 +93,12 @@ namespace cv } return result; } + + inline Mat make_gray(const Mat& image) + { + Mat chs[3]; split(image, chs); + return 0.114 * chs[0] + 0.58 * chs[1] + 0.3 * chs[2]; + } } #endif diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 4f37f32212..8ded955ed5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -198,15 +198,11 @@ TEST(Viz, DISABLED_show_trajectory_reposition) viz.spin(); } - - 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); + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); Affine3d poses[2]; for(int i = 0; i < 2; ++i) @@ -226,6 +222,31 @@ TEST(Viz, show_camera_positions) viz.spin(); } +TEST(Viz, show_overlay_image) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); + + Viz3d viz("show_overlay_image"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.spin(); +} + +TEST(Viz, show_image_3d) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); + + Viz3d viz("show_image_3d"); + viz.showWidget("coos", WCoordinateSystem(100)); + viz.showWidget("img1", WImage3D(lena, Size(lena.cols, lena.rows/2)), makeCameraPose(Vec3d(1.0, 1.0, 1.0), Vec3d::all(0.0), Vec3d(0.0, -1.0, 0.0))); + viz.showWidget("img2", WImage3D(Vec3d(1.0, -1.0, 1.0), Vec3d(-1, 1, -1), Vec3d(0.0, -1.0, 0.0), gray, lena.size())); + + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh mesh = Mesh::load(get_dragon_ply_file_path());