diff --git a/Modules/OpenCVVideoSupport/Testing/CMakeLists.txt b/Modules/OpenCVVideoSupport/Testing/CMakeLists.txt index d45daf111d..5d19e2f864 100644 --- a/Modules/OpenCVVideoSupport/Testing/CMakeLists.txt +++ b/Modules/OpenCVVideoSupport/Testing/CMakeLists.txt @@ -1 +1,7 @@ -MITK_CREATE_MODULE_TESTS() \ No newline at end of file +MITK_CREATE_MODULE_TESTS() +if(BUILD_TESTING AND MODULE_IS_ENABLED) +mitkAddCustomModuleTest(mitkImageToOpenCVImageFilterTest mitkImageToOpenCVImageFilterTest + ${MITK_DATA_DIR}/RenderingTestData/rgbImage.png +) + +endif() diff --git a/Modules/OpenCVVideoSupport/Testing/mitkImageToOpenCVImageFilterTest.cpp b/Modules/OpenCVVideoSupport/Testing/mitkImageToOpenCVImageFilterTest.cpp index 374f3d9dac..d6bd26f3f6 100644 --- a/Modules/OpenCVVideoSupport/Testing/mitkImageToOpenCVImageFilterTest.cpp +++ b/Modules/OpenCVVideoSupport/Testing/mitkImageToOpenCVImageFilterTest.cpp @@ -1,125 +1,167 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkImageToOpenCVImageFilter.h" #include "mitkOpenCVToMitkImageFilter.h" #include #include #include +#include // #include -// #include +#include -/**Documentation - * test for the class "ImageToOpenCVImageFilter". - */ -int mitkImageToOpenCVImageFilterTest(int /*argc*/, char* /*argv*/[]) +mitk::Image::Pointer LoadImage( std::string filename ) { - MITK_TEST_BEGIN("ImageToOpenCVImageFilter") + mitk::ItkImageFileReader::Pointer reader = mitk::ItkImageFileReader::New(); + reader->SetFileName ( filename.c_str() ); + reader->Update(); + if ( reader->GetOutput() == NULL ) + itkGenericExceptionMacro("File "<GetOutput(); + return image; +} - // create itk rgb image - typedef unsigned char PixelType; - typedef itk::Image< itk::RGBPixel, 2 > ImageType; - ImageType::Pointer itkImage = ImageType::New(); - - ImageType::IndexType start; - start[0] = 0; // first index on X - start[1] = 0; // first index on Y - ImageType::SizeType size; - size[0] = 50; // size along X - size[1] = 40; // size along Y - ImageType::RegionType region; - region.SetSize( size ); - region.SetIndex( start ); - itkImage->SetRegions( region ); - itkImage->Allocate(); - - typedef itk::ImageRegionIterator IteratorType; - IteratorType it(itkImage, region); - float twoThirdsTheWidth = size[0] / 4; - unsigned int x=0, y=0; - // create rgb pic - for ( it.GoToBegin(); !it.IsAtEnd(); ++it ) - { - ImageType::PixelType newPixel; - newPixel.SetRed(0); - newPixel.SetGreen(0); - // create asymmetric pic - if( x > twoThirdsTheWidth ) - newPixel.SetBlue(0); - else - newPixel.SetBlue(255); - it.Set(newPixel); - - ++x; - // next line found - if( x == size[0] ) - x = 0; - } - - // debugging -// itk::ImageFileWriter< ImageType >::Pointer writer = itk::ImageFileWriter< ImageType >::New(); -// writer->SetFileName( "c:\\image.png" ); -// writer->SetInput ( itkImage ); -// writer->Update(); - - // import rgb image as MITK image - mitk::Image::Pointer mitkImage = mitk::ImportItkImage( itkImage ); - - mitk::ImageToOpenCVImageFilter::Pointer _ImageToOpenCVImageFilter = - mitk::ImageToOpenCVImageFilter::New(); - - _ImageToOpenCVImageFilter->SetImage( mitkImage ); - - IplImage* openCVImage = _ImageToOpenCVImageFilter->GetOpenCVImage(); - - MITK_TEST_CONDITION_REQUIRED( openCVImage != NULL, "Image returned by filter is not null."); - - // check byte size - const unsigned int expectedSize = size[0] * size[1] * 3 * sizeof( unsigned char);// sizeof( PixelType ); - const unsigned int realSize = openCVImage->width * openCVImage->height * openCVImage->nChannels * sizeof( unsigned char);//* sizeof ( PixelType ); - MITK_TEST_CONDITION_REQUIRED( expectedSize == realSize, "Test expectedSize == realSize"); - - // check pixel values - PixelType expectedBlueValue; - CvScalar s; - for (y = 0; (int)y < openCVImage->height; ++y) - { - for (x = 0; (int)x < openCVImage->width; ++x) +static void testGeneratedImage() +{ + // create itk rgb image + typedef unsigned char PixelType; + typedef itk::Image< itk::RGBPixel, 2 > ImageType; + ImageType::Pointer itkImage = ImageType::New(); + + ImageType::IndexType start; + start[0] = 0; // first index on X + start[1] = 0; // first index on Y + ImageType::SizeType size; + size[0] = 50; // size along X + size[1] = 40; // size along Y + ImageType::RegionType region; + region.SetSize( size ); + region.SetIndex( start ); + itkImage->SetRegions( region ); + itkImage->Allocate(); + + typedef itk::ImageRegionIterator IteratorType; + IteratorType it(itkImage, region); + float twoThirdsTheWidth = size[0] / 4; + unsigned int x=0, y=0; + // create rgb pic + for ( it.GoToBegin(); !it.IsAtEnd(); ++it ) { - expectedBlueValue = 255; - if(x > twoThirdsTheWidth) - expectedBlueValue = 0; + ImageType::PixelType newPixel; + newPixel.SetRed(0); + newPixel.SetGreen(0); + // create asymmetric pic + if( x > twoThirdsTheWidth ) + newPixel.SetBlue(0); + else + newPixel.SetBlue(255); + it.Set(newPixel); + + ++x; + // next line found + if( x == size[0] ) + x = 0; + } + + // debugging + // itk::ImageFileWriter< ImageType >::Pointer writer = itk::ImageFileWriter< ImageType >::New(); + // writer->SetFileName( "c:\\image.png" ); + // writer->SetInput ( itkImage ); + // writer->Update(); - s = cvGet2D(openCVImage,y,x); - if( s.val[0] != expectedBlueValue || s.val[1] != 0 || s.val[2] != 0 ) + // import rgb image as MITK image + mitk::Image::Pointer mitkImage = mitk::ImportItkImage( itkImage ); + + mitk::ImageToOpenCVImageFilter::Pointer _ImageToOpenCVImageFilter = + mitk::ImageToOpenCVImageFilter::New(); + + _ImageToOpenCVImageFilter->SetImage( mitkImage ); + + IplImage* openCVImage = _ImageToOpenCVImageFilter->GetOpenCVImage(); + + MITK_TEST_CONDITION_REQUIRED( openCVImage != NULL, "Image returned by filter is not null."); + + // check byte size + const unsigned int expectedSize = size[0] * size[1] * 3 * sizeof( unsigned char);// sizeof( PixelType ); + const unsigned int realSize = openCVImage->width * openCVImage->height * openCVImage->nChannels * sizeof( unsigned char);//* sizeof ( PixelType ); + MITK_TEST_CONDITION_REQUIRED( expectedSize == realSize, "Test expectedSize == realSize"); + + // check pixel values + PixelType expectedBlueValue; + CvScalar s; + for (y = 0; (int)y < openCVImage->height; ++y) + { + for (x = 0; (int)x < openCVImage->width; ++x) { - std::cout << "Wrong RGB values in created OpenCV image" << std::endl; - throw mitk::TestFailedException(); + expectedBlueValue = 255; + if(x > twoThirdsTheWidth) + expectedBlueValue = 0; + + s = cvGet2D(openCVImage,y,x); + if( s.val[0] != expectedBlueValue || s.val[1] != 0 || s.val[2] != 0 ) + { + std::cout << "Wrong RGB values in created OpenCV image" << std::endl; + throw mitk::TestFailedException(); + } } } - } -// cvNamedWindow( "test" ); -// cvShowImage( "test" , openCVImage ); -// cvWaitKey(); +// cvNamedWindow( "test" ); +// cvShowImage( "test" , openCVImage ); +// cvWaitKey(); + +} + +static void testLoadedImage(mitk::Image::Pointer mitkImage) +{ + mitk::ImageToOpenCVImageFilter::Pointer _ImageToOpenCVImageFilter = + mitk::ImageToOpenCVImageFilter::New(); + + _ImageToOpenCVImageFilter->SetImage( mitkImage ); + + IplImage* openCVImage = _ImageToOpenCVImageFilter->GetOpenCVImage(); + + MITK_TEST_CONDITION_REQUIRED( openCVImage != NULL, "Image returned by filter is not null."); + + CvScalar s; + s=cvGet2D(img,i,j); // get the (i,j) pixel value + printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]); + s.val[0]=111; + s.val[1]=111; + s.val[2]=111; + +// cvNamedWindow( "test" ); +// cvShowImage( "test" , openCVImage ); +// cvWaitKey(); +} + +/**Documentation + * test for the class "ImageToOpenCVImageFilter". + */ +int mitkImageToOpenCVImageFilterTest(int argc, char* argv[]) +{ + MITK_TEST_BEGIN("ImageToOpenCVImageFilter") +testGeneratedImage(); + mitk::Image::Pointer testImage = LoadImage(argv[1]); + testLoadedImage(testImage); // always end with this! MITK_TEST_END(); } diff --git a/Modules/OpenCVVideoSupport/mitkImageToOpenCVImageFilter.h b/Modules/OpenCVVideoSupport/mitkImageToOpenCVImageFilter.h index 26e909c92c..2153ef6212 100644 --- a/Modules/OpenCVVideoSupport/mitkImageToOpenCVImageFilter.h +++ b/Modules/OpenCVVideoSupport/mitkImageToOpenCVImageFilter.h @@ -1,141 +1,162 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkImageToOpenCVImageFilter_h #define mitkImageToOpenCVImageFilter_h #include #include #include #include #include #include +#include #include #include +#include +#include #include "mitkOpenCVVideoSupportExports.h" namespace mitk { /** \brief A pseudo-Filter for creating OpenCV images from MITK images with the option of copying data or referencing it Last contributor: $Author: mueller $ */ class MITK_OPENCVVIDEOSUPPORT_EXPORT ImageToOpenCVImageFilter : public itk::Object { public: typedef itk::RGBPixel< unsigned char > UCRGBPixelType; typedef itk::RGBPixel< unsigned short > USRGBPixelType; typedef itk::RGBPixel< float > FloatRGBPixelType; typedef itk::RGBPixel< double > DoubleRGBPixelType; template static mitk::Image::Pointer ConvertIplToMitkImage( const IplImage * input, bool copyBuffer = true ); mitkClassMacro(ImageToOpenCVImageFilter, itk::Object); itkNewMacro(ImageToOpenCVImageFilter); void SetImage( mitk::Image* _Image ); itkGetMacro(Image, mitk::Image*); bool CheckImage(mitk::Image* image); /// /// Get the produced OpenCVImage. /// ATTENTION: Do not forget to release this image again with cvReleaseImage(). /// IplImage* GetOpenCVImage(); protected: ImageToOpenCVImageFilter(); // purposely hidden virtual ~ImageToOpenCVImageFilter(); int GetDepth(const std::type_info& typeInfo) const; template void ItkImageProcessing( itk::Image* image ); template void ItkImageProcessing( itk::Image,VImageDimension>* image ); protected: /// /// Saves if the filter should copy the data or just reference it /// mitk::WeakPointer m_Image; IplImage* m_OpenCVImage; }; template void mitk::ImageToOpenCVImageFilter::ItkImageProcessing( itk::Image* image ) { + PixelType pType = m_Image->GetPixelType(0); typedef itk::Image ImageType; - + const unsigned int numberOfComponents = pType.GetNumberOfComponents(); const unsigned int numberOfPixels = m_Image->GetDimension(0) * m_Image->GetDimension(1); - const unsigned int numberOfBytes = numberOfPixels * sizeof( typename ImageType::PixelType ); + const unsigned int numberOfValues = numberOfPixels * numberOfComponents; - const typename ImageType::PixelType * itkBuffer = image->GetBufferPointer(); +// const unsigned int numberOfBytes = numberOfValues * sizeof( typename ImageType::PixelType ); + const typename ImageType::PixelType * itkBuffer = image->GetBufferPointer(); typename ImageType::SizeType size = image->GetLargestPossibleRegion().GetSize(); // create new opencv image m_OpenCVImage = cvCreateImage( cvSize( size[0], size[1] ) - , GetDepth(typeid(TPixel)), 1 ); - - memcpy( m_OpenCVImage->imageData, itkBuffer, numberOfBytes ); + , GetDepth(typeid(TPixel)), numberOfComponents ); + const unsigned int stepsize = m_OpenCVImage->widthStep; + const unsigned int width = m_OpenCVImage->width; + const unsigned int height = m_OpenCVImage->height; +// memcpy( m_OpenCVImage->imageData, itkBuffer, numberOfBytes ); + TPixel* mitkImagedata = (TPixel*)m_Image->GetData(); + TPixel* cvdata= reinterpret_cast(m_OpenCVImage->imageData); + for(int y = 0 ; y < height; y++) + { + for(int x = 0 ; x < width*numberOfComponents ; x+=numberOfComponents) + { + for(int c = 0 ; c < numberOfComponents ; c++) + { + cvdata[(numberOfComponents-c-1)+x] =mitkImagedata[x+c]; + } + } + cvdata+= stepsize; + mitkImagedata+= width*numberOfComponents; + } } template void mitk::ImageToOpenCVImageFilter::ItkImageProcessing( itk::Image,VImageDimension>* image ) { typedef itk::RGBPixel RGBPixelType; typedef itk::Image RGBImageType; typedef itk::ImageRegionIterator RGBIteratorType; RGBIteratorType it(image, image->GetLargestPossibleRegion()); typename RGBImageType::SizeType size = image->GetLargestPossibleRegion().GetSize(); // create new opencv image m_OpenCVImage = cvCreateImage( cvSize( size[0], size[1] ), GetDepth(typeid(RGBPixelType)), 3 ); unsigned int x = 0,y = 0; CvScalar s; for ( it.GoToBegin(); !it.IsAtEnd(); ++it ) { s.val[0] = it.Value().GetBlue(); s.val[1] = it.Value().GetGreen(); s.val[2] = it.Value().GetRed(); //MITK_DEBUG << "[" << x << "," << y << "] " << s.val[0] << "(B)," << s.val[1] << "(G)," << s.val[2] << "(R)"; cvSet2D(m_OpenCVImage,y,x,s); ++x; // next line found if( x == size[0] ) { x = 0; ++y; } } } } // namespace #endif // mitkImageToOpenCVImageFilter_h