[osg-users] Volume rendering issues...
Robert Osfield
robert.osfield at gmail.com
Thu Jul 26 06:29:46 PDT 2018
Hi Tom.
My best guess would be that the ITK image data is being deleted prior
to the graphics thread gets a chance copy the data into OpenGL. Try
either copying the data into the osg::Image and let osg::Image then
manage the lifetime of it's own data, or prevent the ITK image data
from getting deleted prior to the osg::Texture3D being used in the
graphics thread - for instance keeping the ITK image object around for
the lifetime of the app, or perhaps more elegantly assigning the ITK
image data via a adapter class that you write to assign it to the
osg:Image as user data.
Robert.
On Thu, 26 Jul 2018 at 14:04, Tom Williamson <tom.williamson at rmit.edu.au> wrote:
>
> Hi gang,
>
> Thanks for all the work on OSG, is rad. I'm currently having a problem with the rendering of a volume, here's what I'm trying to do:
> - I'm using ITK to read a NIFTI file, (segmentation of a bone). The file contains zeros (background) and ones (object), format is unsigned short.
> - I am then normalizing/scaling this and converting it to an osg::Image.
> - I am then attempting to convert this to an osgVolume and display an iso-surface, or at this stage any kind of volume rendering.
> - All the reading, conversion etc. seems to work okay, but I'm getting a read access violation on line 408 of Texture3d.cpp (specifically:Exception thrown at 0x00007FFE64D576B0 (ig9icd64.dll) in RobotSimulation.exe: 0xC0000005: Access violation reading location 0x000002F5732EE070.)
>
> I'm pretty sure I'm just forgetting something very obvious, but if anyone could point out what it is that I'm doing wrong that would be much appreciated. I've put a cut down example of the code below (pretty rough).
> I know that the data is definitely in the osg::image object (wrote it to file, calculated min and max), so I don't necessarily think the conversion is the problem (though could very well be wrong). I'm on a Windows 10 laptop, with a built in Intel graphics card (Intel HD Graphics 620, drivers are up to date), opengl is version 4.5.
> Thanks very much for the help, let me know if you need any other info. Cheers,
> Tom
>
> PS: I'm happy to provide some example data if needed, but I guess this would be more or less the same for any data loaded through ITK and converted to OSG.
> PPS: I've left the code as normal text, it looked somewhat unreadable in the preview, so sorry about that.
>
> [code]
> osg::ref_ptr<osgVolume::Volume> getOsgVolume(std::string filename)
> {
> osg::ref_ptr<osg::Image> osgImage = new osg::Image();
> itk::NiftiImageIOFactory::RegisterOneFactory();
> itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(filename.c_str(), itk::ImageIOFactory::ReadMode);
> imageIO->SetFileName(filename);
> imageIO->ReadImageInformation();
> osg::ref_ptr<osgVolume::Volume> volume = new osgVolume::Volume;
>
> std::cout << "numDimensions: " << imageIO->GetNumberOfDimensions() << std::endl;
> std::cout << "component type: " << imageIO->GetComponentTypeAsString(imageIO->GetComponentType()) << std::endl;
> std::cout << "pixel type: " << imageIO->GetPixelTypeAsString(imageIO->GetPixelType()) << std::endl;
>
> if (imageIO->GetNumberOfDimensions() == 3) {
> typedef itk::Image<unsigned short, 3> imType;
> typedef itk::ImageFileReader<imType> imTypeReader;
>
> imTypeReader::Pointer imageReader = imTypeReader::New();
> imageReader->SetFileName(imageIO->GetFileName());
> imageReader->Update();
>
> imType::RegionType region;
> imType::IndexType start;
> imType::SizeType size;
>
> for (int i = 0; i < imageIO->GetNumberOfDimensions(); ++i) {
> start[i] = 0;
> size[i] = imageIO->GetDimensions(i);
> }
>
> region.SetSize(size);
> region.SetIndex(start);
> typedef itk::MultiplyImageFilter< imType> miType;
> miType::Pointer mif = miType::New();
> mif->SetInput(imageReader->GetOutput());
> mif->SetConstant(pow(2, 16) - 1);
> mif->Update();
> imType::Pointer itkImage = mif->GetOutput();
> region = itkImage->GetBufferedRegion();
> size = region.GetSize();
> start = region.GetIndex();
>
> unsigned int width = size[0];
> unsigned int height = size[1];
> unsigned int depth = size[2];
>
> osg::RefMatrix* matrix = new osg::RefMatrix;
>
> std::cout << "width = " << width << " height = " << height << " depth = " << depth << std::endl;
> for (unsigned int i = 0; i<3; ++i)
> {
> (*matrix)(i, i) = itkImage->GetSpacing()[i];
> }
>
> osgImage->setImage(width, height, depth, GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT, (BYTE*)itkImage->GetBufferPointer(), osg::Image::NO_DELETE, 1, width);
>
> // Setup the transfer function
> osg::ref_ptr<osg::TransferFunction1D> transferFunction = new osg::TransferFunction1D;
> transferFunction->setColor(0.0, osg::Vec4(1.0, 0.0, 0.0, 0.0));
> transferFunction->setColor(0.5, osg::Vec4(1.0, 1.0, 0.0, 0.5));
> transferFunction->setColor(1.0, osg::Vec4(0.0, 0.0, 1.0, 1.0));
>
> // Setup the volume
> osgVolume::ImageDetails* details = new osgVolume::ImageDetails;
> details->setMatrix(matrix);
> osgImage->setUserData(details);
> matrix->preMult(osg::Matrix::scale(double(osgImage->s()), double(osgImage->t()), double(osgImage->r())));
> osg::ref_ptr<osgVolume::VolumeTile> tile = new osgVolume::VolumeTile;
> volume->addChild(tile.get());
> osg::ref_ptr<osgVolume::ImageLayer> layer = new osgVolume::ImageLayer(osgImage.get());
> layer->setLocator(new osgVolume::Locator(*matrix));
> tile->setLocator(new osgVolume::Locator(*matrix));
> tile->setLayer(layer.get());
>
> // Rest of this is setting up the volume rendering...
> float alphaFunc = 0.02f;
>
> osgVolume::AlphaFuncProperty* ap = new osgVolume::AlphaFuncProperty(alphaFunc);
> osgVolume::IsoSurfaceProperty* isop = new osgVolume::IsoSurfaceProperty(alphaFunc);
> osgVolume::SampleDensityProperty* sd = new osgVolume::SampleDensityProperty(0.5f);
> osgVolume::SampleDensityWhenMovingProperty* sdwm = new osgVolume::SampleDensityWhenMovingProperty(0.1);
> osgVolume::SampleRatioProperty* sr = new osgVolume::SampleRatioProperty(1.0f);
> osgVolume::SampleRatioWhenMovingProperty* srwm = new osgVolume::SampleRatioWhenMovingProperty(0.1);
> osgVolume::TransparencyProperty* tp = new osgVolume::TransparencyProperty(1.0);
> osgVolume::TransferFunctionProperty* tfp = new osgVolume::TransferFunctionProperty(transferFunction.get());
> osgVolume::CompositeProperty* cp = new osgVolume::CompositeProperty;
> cp->addProperty(sr);
> cp->addProperty(tp);
> cp->addProperty(isop);
> cp->addProperty(sdwm);
> cp->addProperty(tfp);
>
> layer->addProperty(cp);
> tile->setVolumeTechnique(new osgVolume::MultipassTechnique);
>
> }
> std::cout << "Valid: " << volume.valid() << std::endl;
> return volume;
>
> }
> [/code]
>
> ------------------
> Read this topic online here:
> http://forum.openscenegraph.org/viewtopic.php?p=74384#74384
>
>
>
>
>
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
More information about the osg-users
mailing list