Скопируйте OpenCV IplImage или Mat в Freeimage FIBITMAP

Мне нужно обмениваться данными между FreeImage (FIBITMAP) и форматом OpenCV (IplImage и/или Mat). Я в порядке с получением данных из FIBITMAP в IplImage или Mat, поскольку FreeImage предоставляет вам функцию FreeImage_GetScanLine, которой вы можете установить значение ptr OPenCV imageData равным.

Однако я застрял в том, как сделать обратное, т.е. когда у меня есть изображение OpenCV, как мне получить его данные в изображение FreeImage?


person SSilk    schedule 07.02.2011    source источник


Ответы (3)


Вы должны быть немного осторожны, просто копируя указатель данных, многие форматы изображений имеют отступы, чтобы каждая новая строка начиналась, например, с 4-байтовой границы.

Если ваше изображение имеет функцию GetScanLine(), то, вероятно, безопаснее создать пустой plImage*/cv::Mat и скопировать каждую строку с помощью указателя, возвращаемого из GetScanLine(), и члена .ptr() из cv::MAt.

cv::Mat &src        
int srcRowBytes = width  * src.elemSize();

for (int ih=0;ih<height;ih++) {
    memcpy(dest.pointer_to_row(ih),src.ptr(ih),srcRowBytes);
}
person Martin Beckett    schedule 07.02.2011
comment
как IplImage, так и cv::Mat имеют шаг строки, который существует именно по этой причине (заполнение). - person etarion; 08.02.2011
comment
Да, но можете ли вы узнать, что Freeebitmap использует для степпинга? - person Martin Beckett; 08.02.2011
comment
Существует функция FreeImage_GetPitch, которая возвращает ширину изображения в байтах, такую ​​же, как stepWidth OpenCV. Я попробую это в ближайшее время и дам вам знать, если получится. Спасибо. - person SSilk; 08.02.2011

Вот более подробный код для преобразования. В обеих библиотеках есть много типов данных изображений, я пытался поддерживать наиболее распространенные из них. Это предполагает, что вы передаете cv::Mat в качестве источника. FreeImage имеет перспективу просмотра слева внизу!

/*  These are openCV types
#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
*/

/*  these are FI types
FIT_UNKNOWN = 0,    // unknown type
FIT_BITMAP  = 1,    // standard image           : 1-, 4-, 8-, 16-, 24-, 32-bit
FIT_UINT16  = 2,    // array of unsigned short  : unsigned 16-bit
FIT_INT16   = 3,    // array of short           : signed 16-bit
FIT_UINT32  = 4,    // array of unsigned long   : unsigned 32-bit
FIT_INT32   = 5,    // array of long            : signed 32-bit
FIT_FLOAT   = 6,    // array of float           : 32-bit IEEE floating point
FIT_DOUBLE  = 7,    // array of double          : 64-bit IEEE floating point
FIT_COMPLEX = 8,    // array of FICOMPLEX       : 2 x 64-bit IEEE floating point
FIT_RGB16   = 9,    // 48-bit RGB image         : 3 x 16-bit
FIT_RGBA16  = 10,   // 64-bit RGBA image        : 4 x 16-bit
FIT_RGBF    = 11,   // 96-bit RGB float image   : 3 x 32-bit IEEE floating point
FIT_RGBAF   = 12    // 128-bit RGBA float image : 4 x 32-bit IEEE floating point

*/

if(_dib)  // get rid of the current dib. 
    FreeImage_Unload(_dib);


int width  = src.size().width;
int height = src.size().height;

switch(src.type())
{
case CV_8U  :{_dib = FreeImage_AllocateT(FIT_BITMAP,width, height, 8) ;}break;  // 8  bit grayscale
case CV_8UC3:{_dib = FreeImage_AllocateT(FIT_BITMAP,width, height, 24);}break;  // 24 bit RGB
case CV_16U :{_dib = FreeImage_AllocateT(FIT_UINT16,width, height, 16);}break;  // 16 bit grayscale
case CV_16S :{_dib = FreeImage_AllocateT(FIT_INT16 ,width, height, 16);}break;
case CV_32S :{_dib = FreeImage_AllocateT(FIT_INT32 ,width, height, 32);}break;
case CV_32F :{_dib = FreeImage_AllocateT(FIT_FLOAT ,width, height, 32);}break;
case CV_64F :{_dib = FreeImage_AllocateT(FIT_DOUBLE,width, height, 32);}break;
default:ASSERT(FALSE);
}

if(_dib==NULL)
    return FALSE;


int srcRowBytes = width  * src.elemSize();

for (int ih=0;ih<height;ih++) 
{
    BYTE* ptr2Line = FreeImage_GetScanLine(_dib,(height-1)-ih);
    memcpy(ptr2Line,src.ptr(ih),srcRowBytes);
}
_bHasChanged = TRUE;

return TRUE;
person KiP    schedule 07.03.2013

Что ж, если вы не возражаете против копии, вы можете просто создать заголовок IplImage*/cv::Mat для FIBITMAP, а затем скопировать (используя функцию opencv), например:

cv::Mat src; // your source image
FIBITMAP whatever; // allocate space for your FIBITMAP here
cv::Mat wrapper(height, width, CV_8UC3, ptr_from_FIBITMAP, step);
src.copyTo(wrapper);
person etarion    schedule 07.02.2011