将 OpenCV IplImage 或 Mat 复制到 Freeimage FIBITMAP

发布于 2024-10-16 11:18:30 字数 254 浏览 4 评论 0原文

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

然而,我被困在如何做相反的事情上,即一旦我有了 OpenCV 图像,如何将其数据获取到 FreeImage 图像中?

I need to exchange data between FreeImage (FIBITMAP) and OpenCV format (IplImage and/or Mat). I'm fine with getting data from a FIBITMAP into an IplImage or Mat since FreeImage gives you a function FreeImage_GetScanLine which you can set the OPenCV imageData ptr equal to.

However, I'm stuck on how to do the reverse, i.e. once I have an OpenCV image, how do I get its data into a FreeImage image?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

囍笑 2024-10-23 11:18:31

这是更详细的转换代码。这两个库中有很多图像数据类型,我尝试支持最常见的类型。这假设您传递 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;

Here is a more detailed code for the conversion. There are many image data types in either library, I tried supporting most common ones. This assumes you are passing a cv::Mat as the source. FreeImage has the view perspective of lower left!

/*  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;
寄离 2024-10-23 11:18:31

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

如果您的图像具有 GetScanLine() 函数,那么制作一个空的 plImage*/cv::Mat 并使用从 GetScanLine() 返回的指针和 cv::MAt 的 .ptr() 成员 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);
}

You have to be a little careful just copying the data pointer, a lot of image formats have padding to start each new line on eg a 4byte boundary.

If your image has a GetScanLine() function then it's probably safer to make an empty plImage*/cv::Mat and memcopy each row with the pointer returned from GetScanLine() and the .ptr() member of 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);
}
筱果果 2024-10-23 11:18:31

好吧,如果您不介意复制,您可以为 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);

Well, if you don't mind the copy, you can just create an IplImage*/cv::Mat header for the FIBITMAP and then copy (using the opencv function), like this:

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文