0

我需要在 FreeImage (FIBITMAP) 和 OpenCV 格式(IplImage 和/或 Mat)之间交换数据。我可以将数据从 FIBITMAP 获取到 IplImage 或 Mat 中,因为 FreeImage 为您提供了一个函数 FreeImage_GetScanLine,您可以将 OPenCV imageData ptr 设置为等于该函数。

但是,我被困在如何做相反的事情上,即一旦我有了 OpenCV 图像,我如何将其数据转换为 FreeImage 图像?

4

3 回答 3

1

这是更详细的转换代码。这两个库中都有很多图像数据类型,我尝试支持最常见的类型。这假设您将 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;
于 2013-03-07T18:14:44.833 回答
0

好吧,如果您不介意复制,您可以为 FIBITMAP 创建一个IplImage*/cv::Mat标头,然后复制(使用 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);
于 2011-02-07T22:09:12.417 回答
0

复制数据指针时必须小心一点,许多图像格式都有填充以在例如 4 字节边界上开始每个新行。

如果您的图像具有 GetScanLine() 函数,那么使用从 GetScanLine() 返回的指针和 cv::MAt 的 .ptr() 成员创建一个空的 plImage*/cv::Mat 和 memcopy 每一行可能更安全

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);
}
于 2011-02-07T22:13:58.200 回答