mirror of https://github.com/CGAL/cgal
Merge pull request #7417 from afabri/Polyhedron-nifti-GF
Polyhedron Demo: Add reading NIFTI files (*.nii)
This commit is contained in:
commit
e717b873c5
|
|
@ -150,6 +150,10 @@ public:
|
|||
float ty() const { return image_ptr->ty; }
|
||||
float tz() const { return image_ptr->tz; }
|
||||
|
||||
float& tx(){ return image_ptr->tx; }
|
||||
float& ty(){ return image_ptr->ty; }
|
||||
float& tz(){ return image_ptr->tz; }
|
||||
|
||||
float value(const std::size_t i,
|
||||
const std::size_t j,
|
||||
const std::size_t k) const
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
#include <vtkImageData.h>
|
||||
#include <vtkDICOMImageReader.h>
|
||||
#include <vtkBMPReader.h>
|
||||
#include <vtkNIFTIImageReader.h>
|
||||
#include <vtkImageReader.h>
|
||||
#include <vtkImageGaussianSmooth.h>
|
||||
#include <vtkDemandDrivenPipeline.h>
|
||||
|
|
@ -1086,9 +1087,10 @@ private Q_SLOTS:
|
|||
QString Io_image_plugin::nameFilters() const
|
||||
{
|
||||
return QString("Inrimage files (*.inr *.inr.gz) ;; "
|
||||
"Analyze files (*.hdr *.img *img.gz) ;; "
|
||||
"Analyze files (*.hdr *.img *.img.gz) ;; "
|
||||
"Stanford Exploration Project files (*.H *.HH) ;; "
|
||||
"NRRD image files (*.nrrd)");
|
||||
"NRRD image files (*.nrrd) ;; "
|
||||
"NIFTI image files (*.nii)");
|
||||
}
|
||||
|
||||
bool Io_image_plugin::canLoad(QFileInfo) const
|
||||
|
|
@ -1143,6 +1145,23 @@ Io_image_plugin::load(QFileInfo fileinfo, bool& ok, bool add_to_scene)
|
|||
#endif
|
||||
}
|
||||
|
||||
// read a NIFTI file
|
||||
if(fileinfo.suffix() == "nii")
|
||||
{
|
||||
#ifdef CGAL_USE_VTK
|
||||
vtkNew<vtkNIFTIImageReader> reader;
|
||||
reader->SetFileName(fileinfo.filePath().toUtf8());
|
||||
reader->Update();
|
||||
auto vtk_image = reader->GetOutput();
|
||||
vtk_image->Print(std::cerr);
|
||||
*image = CGAL::IO::read_vtk_image_data(vtk_image); // copy the image data
|
||||
#else
|
||||
CGAL::Three::Three::warning("VTK is required to read NIfTI files");
|
||||
delete image;
|
||||
return QList<Scene_item*>();
|
||||
#endif
|
||||
}
|
||||
|
||||
// read a sep file
|
||||
else if (fileinfo.suffix() == "H" || fileinfo.suffix() == "HH")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ typedef Edge_container Ec;
|
|||
typedef Viewer_interface Vi;
|
||||
namespace internal {
|
||||
|
||||
template <typename Word_type>
|
||||
class Image_accessor
|
||||
{
|
||||
public:
|
||||
|
|
@ -33,47 +34,47 @@ public:
|
|||
int dx() const { return dx_; }
|
||||
int dy() const { return dy_; }
|
||||
int dz() const { return dz_; }
|
||||
std::size_t xdim() const { return im_.xdim(); }
|
||||
std::size_t ydim() const { return im_.ydim(); }
|
||||
std::size_t zdim() const { return im_.zdim(); }
|
||||
double vx() const { return im_.vx(); }
|
||||
double vy() const { return im_.vy(); }
|
||||
double vz() const { return im_.vz(); }
|
||||
std::size_t xdim() const { return im_->xdim(); }
|
||||
std::size_t ydim() const { return im_->ydim(); }
|
||||
std::size_t zdim() const { return im_->zdim(); }
|
||||
double vx() const { return im_->vx(); }
|
||||
double vy() const { return im_->vy(); }
|
||||
double vz() const { return im_->vz(); }
|
||||
|
||||
double tx() const { return im_.image()->tx; }
|
||||
double ty() const { return im_.image()->ty; }
|
||||
double tz() const { return im_.image()->tz; }
|
||||
double tx() const { return im_->image()->tx; }
|
||||
double ty() const { return im_->image()->ty; }
|
||||
double tz() const { return im_->image()->tz; }
|
||||
|
||||
private:
|
||||
unsigned char non_null_neighbor_data(std::size_t i,
|
||||
Word_type non_null_neighbor_data(std::size_t i,
|
||||
std::size_t j,
|
||||
std::size_t k) const;
|
||||
|
||||
unsigned char image_data(std::size_t i, std::size_t j, std::size_t k) const;
|
||||
Word_type image_data(std::size_t i, std::size_t j, std::size_t k) const;
|
||||
|
||||
void add_to_normal(unsigned char v,
|
||||
void add_to_normal(Word_type v,
|
||||
float& x, float& y, float& z,
|
||||
int dx, int dy, int dz) const;
|
||||
|
||||
private:
|
||||
const Image& im_;
|
||||
const Image* im_;
|
||||
int dx_, dy_, dz_;
|
||||
const QColor default_color_;
|
||||
std::map<unsigned char, QColor> colors_;
|
||||
QColor default_color_;
|
||||
std::map<Word_type, QColor> colors_;
|
||||
};
|
||||
|
||||
|
||||
Image_accessor::Image_accessor(const Image& im, int dx, int dy, int dz)
|
||||
: im_(im)
|
||||
template <typename Word_type>
|
||||
Image_accessor<Word_type>::Image_accessor(const Image& im, int dx, int dy, int dz)
|
||||
: im_(&im)
|
||||
, dx_(dx)
|
||||
, dy_(dy)
|
||||
, dz_(dz)
|
||||
, default_color_()
|
||||
, colors_()
|
||||
{
|
||||
const std::size_t xdim = im_.xdim();
|
||||
const std::size_t ydim = im_.ydim();
|
||||
const std::size_t zdim = im_.zdim();
|
||||
const std::size_t xdim = im_->xdim();
|
||||
const std::size_t ydim = im_->ydim();
|
||||
const std::size_t zdim = im_->zdim();
|
||||
|
||||
for(std::size_t i=0 ; i<xdim ; i+=dx_)
|
||||
{
|
||||
|
|
@ -81,7 +82,7 @@ Image_accessor::Image_accessor(const Image& im, int dx, int dy, int dz)
|
|||
{
|
||||
for(std::size_t k=0 ; k<zdim ; k+=dz_)
|
||||
{
|
||||
unsigned char c = image_data(i,j,k);
|
||||
Word_type c = image_data(i,j,k);
|
||||
if ( 0 != c ) { colors_.insert(std::make_pair(c,QColor())); }
|
||||
}
|
||||
}
|
||||
|
|
@ -89,7 +90,7 @@ Image_accessor::Image_accessor(const Image& im, int dx, int dy, int dz)
|
|||
|
||||
double i=0;
|
||||
const double starting_hue = 45./360.; // magenta
|
||||
for ( std::map<unsigned char, QColor>::iterator it = colors_.begin(),
|
||||
for ( auto it = colors_.begin(),
|
||||
end = colors_.end() ; it != end ; ++it, i += 1.)
|
||||
{
|
||||
double hue = starting_hue + 1./double(colors_.size()) * i;
|
||||
|
|
@ -98,18 +99,19 @@ Image_accessor::Image_accessor(const Image& im, int dx, int dy, int dz)
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
bool
|
||||
Image_accessor::
|
||||
Image_accessor<Word_type>::
|
||||
is_vertex_active(std::size_t i, std::size_t j, std::size_t k) const
|
||||
{
|
||||
unsigned char v1 = image_data(i-dx_, j-dy_, k-dz_);
|
||||
unsigned char v2 = image_data(i-dx_, j-dy_, k );
|
||||
unsigned char v3 = image_data(i-dx_, j , k-dz_);
|
||||
unsigned char v4 = image_data(i-dx_, j , k );
|
||||
unsigned char v5 = image_data(i , j-dy_, k-dz_);
|
||||
unsigned char v6 = image_data(i , j-dy_, k );
|
||||
unsigned char v7 = image_data(i , j , k-dz_);
|
||||
unsigned char v8 = image_data(i , j , k );
|
||||
Word_type v1 = image_data(i-dx_, j-dy_, k-dz_);
|
||||
Word_type v2 = image_data(i-dx_, j-dy_, k );
|
||||
Word_type v3 = image_data(i-dx_, j , k-dz_);
|
||||
Word_type v4 = image_data(i-dx_, j , k );
|
||||
Word_type v5 = image_data(i , j-dy_, k-dz_);
|
||||
Word_type v6 = image_data(i , j-dy_, k );
|
||||
Word_type v7 = image_data(i , j , k-dz_);
|
||||
Word_type v8 = image_data(i , j , k );
|
||||
|
||||
// don't draw interior vertices
|
||||
if ( v1 != 0 && v2 != 0 && v3 != 0 && v4 != 0 &&
|
||||
|
|
@ -121,33 +123,35 @@ is_vertex_active(std::size_t i, std::size_t j, std::size_t k) const
|
|||
return ( v1 != 0 || v2 != 0 || v3 != 0 || v4 != 0 ||
|
||||
v5 != 0 || v6 != 0 || v7 != 0 || v8 != 0 );
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
const QColor&
|
||||
Image_accessor::vertex_color(std::size_t i, std::size_t j, std::size_t k) const
|
||||
Image_accessor<Word_type>::vertex_color(std::size_t i, std::size_t j, std::size_t k) const
|
||||
{
|
||||
unsigned char c = non_null_neighbor_data(i,j,k);
|
||||
Word_type c = non_null_neighbor_data(i,j,k);
|
||||
if ( 0 == c ) { return default_color_; }
|
||||
|
||||
std::map<unsigned char, QColor>::const_iterator color = colors_.find(c);
|
||||
auto color = colors_.find(c);
|
||||
if ( colors_.end() == color ) { return default_color_; }
|
||||
|
||||
return color->second;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
Image_accessor::image_data(std::size_t i, std::size_t j, std::size_t k) const
|
||||
template <typename Word_type>
|
||||
Word_type
|
||||
Image_accessor<Word_type>::image_data(std::size_t i, std::size_t j, std::size_t k) const
|
||||
{
|
||||
if ( i<im_.xdim() && j<im_.ydim() && k<im_.zdim() )
|
||||
return CGAL::IMAGEIO::static_evaluate<unsigned char>(im_.image(),i,j,k);
|
||||
if ( i<im_->xdim() && j<im_->ydim() && k<im_->zdim() )
|
||||
return CGAL::IMAGEIO::static_evaluate<Word_type>(im_->image(),i,j,k);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
Image_accessor::
|
||||
template <typename Word_type>
|
||||
Word_type
|
||||
Image_accessor<Word_type>::
|
||||
non_null_neighbor_data(std::size_t i, std::size_t j, std::size_t k) const
|
||||
{
|
||||
unsigned char v = image_data(i-dx_, j-dy_, k-dz_);
|
||||
Word_type v = image_data(i-dx_, j-dy_, k-dz_);
|
||||
if ( v != 0 ) { return v; }
|
||||
|
||||
v = image_data(i-dx_, j-dy_, k );
|
||||
|
|
@ -174,12 +178,13 @@ non_null_neighbor_data(std::size_t i, std::size_t j, std::size_t k) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Image_accessor::
|
||||
Image_accessor<Word_type>::
|
||||
normal(std::size_t i, std::size_t j, std::size_t k,
|
||||
float& x, float& y, float& z) const
|
||||
{
|
||||
unsigned char v = image_data(i-dx_, j-dy_, k-dz_);
|
||||
Word_type v = image_data(i-dx_, j-dy_, k-dz_);
|
||||
add_to_normal(v,x,y,z, 1 , 1 , 1);
|
||||
|
||||
v = image_data( i-dx_, j-dy_, k);
|
||||
|
|
@ -204,9 +209,10 @@ normal(std::size_t i, std::size_t j, std::size_t k,
|
|||
add_to_normal(v,x,y,z, -1 , -1 , -1);
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Image_accessor::
|
||||
add_to_normal(unsigned char v,
|
||||
Image_accessor<Word_type>::
|
||||
add_to_normal(Word_type v,
|
||||
float& x, float& y, float& z,
|
||||
int dx, int dy, int dz) const
|
||||
{
|
||||
|
|
@ -218,14 +224,11 @@ add_to_normal(unsigned char v,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Vertex_buffer_helper
|
||||
{
|
||||
public:
|
||||
Vertex_buffer_helper(const Image_accessor& data, bool is_ogl_4_3);
|
||||
|
||||
void fill_buffer_data();
|
||||
virtual void fill_buffer_data() = 0;
|
||||
virtual ~Vertex_buffer_helper() {}
|
||||
|
||||
float* colors() { return colors_.data(); }
|
||||
float* normals() { return normals_.data(); }
|
||||
|
|
@ -236,6 +239,19 @@ public:
|
|||
std::size_t normal_size() const { return normals_.size(); }
|
||||
std::size_t vertex_size() const { return vertices_.size(); }
|
||||
std::size_t quad_size() const { return quads_.size(); }
|
||||
protected:
|
||||
std::vector<float> colors_, normals_, vertices_;
|
||||
std::vector<unsigned int> quads_;
|
||||
};
|
||||
|
||||
template <typename Word_type>
|
||||
class Vertex_buffer_helper_impl : public Vertex_buffer_helper
|
||||
{
|
||||
public:
|
||||
Vertex_buffer_helper_impl(Image_accessor<Word_type>&& data, bool is_ogl_4_3);
|
||||
|
||||
~Vertex_buffer_helper_impl() override {}
|
||||
void fill_buffer_data() override;
|
||||
|
||||
private:
|
||||
void treat_vertex(std::size_t i, std::size_t j, std::size_t k);
|
||||
|
|
@ -254,26 +270,28 @@ private:
|
|||
int dz() const { return data_.dz(); }
|
||||
|
||||
private:
|
||||
static int vertex_not_found_;
|
||||
static constexpr int vertex_not_found_ = -1;
|
||||
|
||||
const Image_accessor& data_;
|
||||
const Image_accessor<Word_type> data_;
|
||||
typedef std::map<int, std::size_t> Indices;
|
||||
Indices indices_;
|
||||
std::vector<float> colors_, normals_, vertices_;
|
||||
std::vector<unsigned int> quads_;
|
||||
bool is_ogl_4_3;
|
||||
};
|
||||
|
||||
int Vertex_buffer_helper::vertex_not_found_ = -1;
|
||||
// template <typename Word_type>
|
||||
// int Vertex_buffer_helper_impl<Word_type>::vertex_not_found_ = -1;
|
||||
|
||||
Vertex_buffer_helper::
|
||||
Vertex_buffer_helper(const Image_accessor& data, bool b)
|
||||
: data_(data), is_ogl_4_3(b)
|
||||
|
||||
template <typename Word_type>
|
||||
Vertex_buffer_helper_impl<Word_type>::
|
||||
Vertex_buffer_helper_impl(Image_accessor<Word_type>&& data, bool b)
|
||||
: data_(std::move(data)), is_ogl_4_3(b)
|
||||
{}
|
||||
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Vertex_buffer_helper::
|
||||
Vertex_buffer_helper_impl<Word_type>::
|
||||
fill_buffer_data()
|
||||
{
|
||||
std::size_t i,j,k;
|
||||
|
|
@ -289,8 +307,9 @@ fill_buffer_data()
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Vertex_buffer_helper::treat_vertex(std::size_t i, std::size_t j, std::size_t k)
|
||||
Vertex_buffer_helper_impl<Word_type>::treat_vertex(std::size_t i, std::size_t j, std::size_t k)
|
||||
{
|
||||
if ( data_.is_vertex_active(i,j,k) )
|
||||
{
|
||||
|
|
@ -301,8 +320,9 @@ Vertex_buffer_helper::treat_vertex(std::size_t i, std::size_t j, std::size_t k)
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Vertex_buffer_helper::push_color(std::size_t i, std::size_t j, std::size_t k)
|
||||
Vertex_buffer_helper_impl<Word_type>::push_color(std::size_t i, std::size_t j, std::size_t k)
|
||||
{
|
||||
const QColor& color = data_.vertex_color(i,j,k);
|
||||
if ( ! color.isValid() ) { return; }
|
||||
|
|
@ -311,8 +331,9 @@ Vertex_buffer_helper::push_color(std::size_t i, std::size_t j, std::size_t k)
|
|||
colors_.push_back(float(color.blue())/255.f);
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Vertex_buffer_helper::push_normal(std::size_t i, std::size_t j, std::size_t k)
|
||||
Vertex_buffer_helper_impl<Word_type>::push_normal(std::size_t i, std::size_t j, std::size_t k)
|
||||
{
|
||||
float x=0.f, y=0.f, z=0.f;
|
||||
data_.normal(i,j,k,x,y,z);
|
||||
|
|
@ -327,8 +348,9 @@ Vertex_buffer_helper::push_normal(std::size_t i, std::size_t j, std::size_t k)
|
|||
normals_.push_back(z);
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Vertex_buffer_helper::push_vertex(std::size_t i, std::size_t j, std::size_t k)
|
||||
Vertex_buffer_helper_impl<Word_type>::push_vertex(std::size_t i, std::size_t j, std::size_t k)
|
||||
{
|
||||
indices_.insert(std::make_pair(compute_position(i,j,k),
|
||||
vertices_.size()/3));
|
||||
|
|
@ -352,8 +374,9 @@ Vertex_buffer_helper::push_vertex(std::size_t i, std::size_t j, std::size_t k)
|
|||
vertices_.push_back( (dk - 0.5) * data_.vz() + data_.tz());
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Vertex_buffer_helper::push_quads(std::size_t i, std::size_t j, std::size_t k)
|
||||
Vertex_buffer_helper_impl<Word_type>::push_quads(std::size_t i, std::size_t j, std::size_t k)
|
||||
{
|
||||
int pos1 = vertex_index(i-dx(), j , k);
|
||||
int pos2 = vertex_index(i-dx(), j-dy(), k);
|
||||
|
|
@ -372,8 +395,9 @@ Vertex_buffer_helper::push_quads(std::size_t i, std::size_t j, std::size_t k)
|
|||
push_quad(pos1, pos2, pos3, pos4);
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
void
|
||||
Vertex_buffer_helper::push_quad(int pos1, int pos2, int pos3, int pos4)
|
||||
Vertex_buffer_helper_impl<Word_type>::push_quad(int pos1, int pos2, int pos3, int pos4)
|
||||
{
|
||||
if ( pos1 != vertex_not_found_
|
||||
&& pos2 != vertex_not_found_
|
||||
|
|
@ -391,8 +415,9 @@ Vertex_buffer_helper::push_quad(int pos1, int pos2, int pos3, int pos4)
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
int
|
||||
Vertex_buffer_helper::
|
||||
Vertex_buffer_helper_impl<Word_type>::
|
||||
compute_position(std::size_t i, std::size_t j, std::size_t k) const
|
||||
{
|
||||
return static_cast<int>(
|
||||
|
|
@ -401,8 +426,9 @@ compute_position(std::size_t i, std::size_t j, std::size_t k) const
|
|||
+ k/dz());
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
int
|
||||
Vertex_buffer_helper::
|
||||
Vertex_buffer_helper_impl<Word_type>::
|
||||
vertex_index(std::size_t i, std::size_t j, std::size_t k) const
|
||||
{
|
||||
if ( i > data_.xdim() || j > data_.ydim() || k > data_.zdim() )
|
||||
|
|
@ -751,17 +777,30 @@ void Scene_image_item::initializeBuffers(Viewer_interface *v) const
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Word_type>
|
||||
internal::Vertex_buffer_helper*
|
||||
init_helper(const Image &im, int dx, int dy, int dz, bool is_ogl_4_3)
|
||||
{
|
||||
internal::Image_accessor<Word_type> image_data_accessor(im, dx, dy, dz);
|
||||
return new internal::Vertex_buffer_helper_impl<Word_type>(std::move(image_data_accessor),
|
||||
is_ogl_4_3);
|
||||
}
|
||||
|
||||
void Scene_image_item::computeElements() const
|
||||
{
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
d->draw_Bbox(bbox(), &d->v_box);
|
||||
if(!d->is_hidden)
|
||||
{
|
||||
internal::Image_accessor image_data_accessor (*m_image,
|
||||
d->m_voxel_scale,
|
||||
d->m_voxel_scale,
|
||||
d->m_voxel_scale);
|
||||
d->helper = new internal::Vertex_buffer_helper(image_data_accessor, d->is_ogl_4_3);
|
||||
// internal::Image_accessor image_data_accessor (*m_image,
|
||||
// d->m_voxel_scale,
|
||||
// d->m_voxel_scale,
|
||||
// d->m_voxel_scale);
|
||||
// d->helper = new internal::Vertex_buffer_helper(image_data_accessor, d->is_ogl_4_3);
|
||||
CGAL_IMAGE_IO_CASE(m_image->image(),
|
||||
d->helper = init_helper<Word>(*m_image,
|
||||
d->m_voxel_scale, d->m_voxel_scale, d->m_voxel_scale,
|
||||
d->is_ogl_4_3));
|
||||
d->helper->fill_buffer_data();
|
||||
getTriangleContainer(0)->allocate(
|
||||
Tc::Smooth_vertices,
|
||||
|
|
|
|||
Loading…
Reference in New Issue