1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
/*=========================================================================
*
* Copyright Insight Software Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#ifndef itkOpenCVImageBridge_h
#define itkOpenCVImageBridge_h
#include <string>
#include "itkImage.h"
#include "itkDefaultConvertPixelTraits.h"
#include "itkConvertPixelBuffer.h"
#include "cv.h"
#include "highgui.h"
namespace itk
{
/** \class OpenCVImageBridge
* \brief This class provides static methods to convert between OpenCV images
* and itk::Image
*
* This class provides methods for the following conversions:
* IplImage -> itk::Image
* cv::Mat -> itk::Image
* itk::Image -> IplImage
* itk::Image -> cv::Mat
*
* Each method is templated over the type of itk::Image used. The conversions
* copy the data and convert between types if necessary.
*
* \ingroup ITKVideoBridgeOpenCV
*/
class OpenCVImageBridge
{
public:
/** ITK stype typedefs */
typedef OpenCVImageBridge Self;
/** IplImage* -> itk::Image */
template<typename TOutputImageType>
static typename TOutputImageType::Pointer IplImageToITKImage(const IplImage* in);
/** cv::Mat -> itk::Image */
template<typename TOutputImageType>
static typename TOutputImageType::Pointer CVMatToITKImage(const cv::Mat & in);
/** itk::Image -> IplImage* */
template<typename TInputImageType>
static IplImage* ITKImageToIplImage(const TInputImageType* in, bool force3Channels = false);
/** itk::Image -> cv::Mat */
template<typename TInputImageType>
static cv::Mat ITKImageToCVMat(const TInputImageType* in, bool force3Channels = false);
private:
OpenCVImageBridge(const Self &) ITK_DELETE_FUNCTION;
void operator=(const Self &) ITK_DELETE_FUNCTION;
/** Steps involved in this method are:
1) Handle converting between colorspaces
2) Allocate the output image
3) Create a copy of the current IplImage's buffer without any padding
(slow but necessary)
4) Copy the buffer and convert the pixels if necessary */
template< typename TOutputImageType, typename TPixel >
static void ITKConvertIplImageBuffer( const IplImage* in,
TOutputImageType* out,
int iDepth )
{
// Typedefs
typedef TOutputImageType ImageType;
typedef typename ImageType::PixelType OutputPixelType;
typedef DefaultConvertPixelTraits<OutputPixelType> ConvertPixelTraits;
unsigned int inChannels = in->nChannels;
unsigned int outChannels = itk::NumericTraits<OutputPixelType>::MeasurementVectorType::Dimension;
// We only change current if it no longer points at in, so this is safe
IplImage* current = const_cast<IplImage*>(in);
bool isVectorImage(strcmp(out->GetNameOfClass(), "VectorImage") == 0);
bool freeCurrent = false;
if (inChannels == 3 && outChannels == 1)
{
current = cvCreateImage(cvSize(in->width, in->height), iDepth, 1);
cvCvtColor(in, current, CV_BGR2GRAY);
freeCurrent = true;
}
else if (inChannels == 1 && outChannels == 3)
{
current = cvCreateImage(cvSize(in->width, in->height), iDepth, 3);
cvCvtColor(in, current, CV_GRAY2RGB);
freeCurrent = true;
}
else if (inChannels == 3 && outChannels == 3)
{
current = cvCreateImage(cvSize(in->width, in->height), iDepth, 3);
cvCvtColor(in, current, CV_BGR2RGB);
freeCurrent = true;
}
else if (inChannels != 1 || outChannels != 1)
{
itkGenericExceptionMacro("Conversion from " << inChannels << " channels to "
<< outChannels << " channels is not supported");
}
typename ImageType::RegionType region;
typename ImageType::RegionType::SizeType size;
typename ImageType::RegionType::IndexType start;
typename ImageType::SpacingType spacing;
size.Fill( 1 );
size[0] = current->width;
size[1] = current->height;
start.Fill(0);
spacing.Fill(1);
region.SetSize(size);
region.SetIndex(start);
out->SetRegions(region);
out->SetSpacing(spacing);
out->Allocate();
size_t lineLength = current->width*current->nChannels;
void* unpaddedBuffer = reinterpret_cast< void* >(
new TPixel[current->height*lineLength]);
unsigned int paddedBufPos = 0;
unsigned int unpaddedBufPos = 0;
for (int i = 0; i < current->height; ++i)
{
memcpy(&(reinterpret_cast<TPixel*>(unpaddedBuffer)[unpaddedBufPos]),
reinterpret_cast<TPixel*>(current->imageData + paddedBufPos),
lineLength*sizeof(TPixel) );
paddedBufPos += current->widthStep;
unpaddedBufPos += lineLength;
}
if (isVectorImage)
{
ConvertPixelBuffer<TPixel, OutputPixelType, ConvertPixelTraits>
::ConvertVectorImage(static_cast< TPixel* >(unpaddedBuffer),
current->nChannels,
out->GetPixelContainer()->GetBufferPointer(),
out->GetPixelContainer()->Size());
}
else
{
ConvertPixelBuffer<TPixel, OutputPixelType, ConvertPixelTraits>
::Convert(static_cast< TPixel* >(unpaddedBuffer),
current->nChannels,
out->GetPixelContainer()->GetBufferPointer(),
out->GetPixelContainer()->Size());
}
delete[] reinterpret_cast<TPixel*>(unpaddedBuffer);
if (freeCurrent)
{
cvReleaseImage(¤t);
}
}
template< typename TPixel, unsigned int VDimension >
struct HandleRGBPixel
{
static void Padding( const Image< TPixel, VDimension >* itkNotUsed( in ),
IplImage* itkNotUsed( out ) )
{}
};
template< typename TValue, unsigned int VDimension >
struct HandleRGBPixel< RGBPixel< TValue >, VDimension >
{
typedef TValue ValueType;
typedef RGBPixel< ValueType > PixelType;
typedef Image< PixelType, VDimension > ImageType;
static void Padding( const ImageType* in, IplImage* out )
{
typename ImageType::IndexType pixelIndex = {{0,0}};
for( int r=0;r < out->height; r++ )
{
ValueType* ptr = reinterpret_cast< ValueType* >( out->imageData + r * out->widthStep );
for( int c=0;c < out->width; c++ )
{
pixelIndex[0] = c;
pixelIndex[1] = r;
typename ImageType::PixelType pixel = in->GetPixel(pixelIndex);
for( unsigned int i=0; i< 3; i++ )
{
*ptr++ = pixel[i];
}
}
}
}
};
}; // end class OpenCVImageBridge
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkOpenCVImageBridge.hxx"
#endif
#endif
|