created tests for images, created vtk/vtkImageMatSource, and switched all images to that class

This commit is contained in:
Anatoly Baksheev 2014-01-10 01:57:11 +04:00
parent 462d516743
commit f37c31742a
12 changed files with 286 additions and 97 deletions

View File

@ -125,6 +125,7 @@
#include <vtkOBJExporter.h>
#include <vtkVRMLExporter.h>
#include <vtkTensorGlyph.h>
#include <vtkImageAlgorithm.h>
#if !defined(_WIN32) || defined(__CYGWIN__)
# include <unistd.h> /* unlink */
@ -137,6 +138,7 @@
#include <vtk/vtkCloudMatSink.h>
#include <vtk/vtkCloudMatSource.h>
#include <vtk/vtkTrajectorySource.h>
#include <vtk/vtkImageMatSource.h>
#include <opencv2/core.hpp>
#include <opencv2/viz.hpp>

View File

@ -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<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
source->SetImage(image);
// Need to flip the image as the coordinates are different in OpenCV and VTK
vtkSmartPointer<vtkImageFlip> flip_filter = vtkSmartPointer<vtkImageFlip>::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<vtkTransform> transform = vtkSmartPointer<vtkTransform>::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<vtkImageMapper> image_mapper = vtkSmartPointer<vtkImageMapper>::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<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
source->SetImage(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->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<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
source->SetImage(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->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<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
source->SetImage(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->SetInputConnection(source->GetOutputPort());
flipFilter->Update();
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::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<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
source->SetImage(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->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<vtkImageData> vtk_image = vtkSmartPointer<vtkImageData>::New();
ConvertToVtkImage::convert(image, vtk_image);
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
source->SetImage(image);
source->Update();
vtkSmartPointer<vtkImageData> vtk_image = source->GetOutput();
// Adjust a pixel of the vtk_image
if(image.channels() == 1)

View File

@ -179,67 +179,4 @@ private:
bool removeActorFromRenderer(const vtkSmartPointer<vtkProp> &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<vtkImageData> output, color_tag tag)
{
for (int y = 0; y < source.rows; ++y)
{
const uchar *srow = source.ptr<uchar>(y);
for (int x = 0; x < source.cols; ++x, srow += source.channels())
*reinterpret_cast<Vec3b*>(output->GetScalarPointer(x,y,0)) = fetchRgb(srow, tag);
}
output->Modified();
}
static void copyImage(const Mat &source, vtkSmartPointer<vtkImageData> output, gray_tag)
{
for (int y = 0; y < source.rows; ++y)
{
const uchar *srow = source.ptr<uchar>(y);
for (int x = 0; x < source.cols; ++x)
*reinterpret_cast<uchar*>(output->GetScalarPointer(x,y,0)) = *srow++;
}
output->Modified();
}
};
static void convert(const Mat &image, vtkSmartPointer<vtkImageData> 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

View File

@ -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());

View File

@ -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());

View File

@ -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<vtkImageData> output)
{
for (int y = 0; y < source.rows; ++y)
{
const unsigned char *srow = source.ptr<unsigned char>(y);
for (int x = 0; x < source.cols; ++x)
*reinterpret_cast<unsigned char*>(output->GetScalarPointer(x,y,0)) = *srow++;
}
}
void cv::viz::vtkImageMatSource::copyRGBImage(const Mat &source, vtkSmartPointer<vtkImageData> output)
{
for (int y = 0; y < source.rows; ++y)
{
const unsigned char *srow = source.ptr<unsigned char>(y);
for (int x = 0; x < source.cols; ++x, srow += source.channels())
*reinterpret_cast<Vec3b*>(output->GetScalarPointer(x,y,0)) = Vec3b(srow[2], srow[1], srow[0]);
}
}
void cv::viz::vtkImageMatSource::copyRGBAImage(const Mat &source, vtkSmartPointer<vtkImageData> output)
{
for (int y = 0; y < source.rows; ++y)
{
const unsigned char *srow = source.ptr<unsigned char>(y);
for (int x = 0; x < source.cols; ++x, srow += source.channels())
*reinterpret_cast<Vec4b*>(output->GetScalarPointer(x,y,0)) = Vec4b(srow[2], srow[1], srow[0], srow[3]);
}
}

View File

@ -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<vtkImageData> 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<vtkImageData> output);
static void copyRGBImage (const Mat &source, vtkSmartPointer<vtkImageData> output);
static void copyRGBAImage(const Mat &source, vtkSmartPointer<vtkImageData> output);
};
}
}
#endif

View File

@ -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);

View File

@ -59,7 +59,7 @@ namespace cv
{
public:
static vtkTrajectorySource *New();
vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm);
vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm)
virtual void SetTrajectory(InputArray trajectory);

View File

@ -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();

View File

@ -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

View File

@ -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_<double>(viz.getWindowSize()) * 0.5)));
viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size_<double>(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());