首页 > 学院 > 开发设计 > 正文

使用FreeImage帮助OpenCV读出更多图像(转)

2019-11-06 06:52:45
字体:
来源:转载
供稿:网友

使用FreeImage帮助OpenCV读出更多图像(转)

(2014-03-20 09:21:12)转载
  

OpenCV读图像的能力比较弱,尤其是对常见的 Tiff 支持得很差。通过研究 OpenCV 的源代码,发现它针对 Tiff 只能读出以 LZW 和 JPEG 两种压缩格式保存的单页 RGBA 图像,而大量使用的 G4 等二值化图像和多页图像的 Tiff 文件是不能被 OpenCV 直接读出的。这可以使用 libTiff 帮助读入这些 Tiff 文件。不过使用 FreeImage 更好一些。因为在 FreeImage 中已经把 libTiff 封装成一个 filter 了,FreeImage 提供了一个高层的图像访问统一接口,支持了大量的图像编解码 filter,并且能够找到大量基于 FreeImage 的 filter ,所以使用 FreeImage 是一个更好的选择。当读入图像的位深度小于一个字节时,不能直接在 opencv 中创建 iplImage,可以使用 FreeImage 将这类图像转化为灰度图像,然后再输入 opencv 中。另一个需要注意的是 FreeImage 中的图像如果直接输入 IplImage,则出现了水平翻转,因此不能直接使用从 FreeImage 获得的图像作为 IplImage 的数据。以下是一段把 FreeImage 的位图转换成 opencv 图像的示例代码(片段):void zig_image_group::load_bitmap(FIBITMAP* bitmap)    if (!bitmap) return;    // 取得位图数据    unsigned int imageWidth FreeImage_GetWidth(bitmap);    unsigned int imageHeight FreeImage_GetHeight(bitmap);    unsigned short channels 1;    unsigned short depth FreeImage_GetBPP(bitmap);    FIBITMAP bitmap_temp 0;    unsigned char data 0;    if (depth 8)        // opencv 只能创建 位的图像        depth 8;        if( NULL != (bitmap_temp FreeImage_ConvertToGreyscale(bitmap))            data FreeImage_GetBits(bitmap_temp);           else        assert (depth == 0);        channels depth 8;        depth 8;        data FreeImage_GetBits(bitmap);       // 创建 opencv 图像,读入位图信息    if(data)        CvSize size cvSize((int) imageWidth, (int) imageHeight);        // 如果直接从 FreeImage 得到图像,则进行了水平翻转,因此需要使用一个中间图像来纠正翻转        // 同时因为从 FreeImage 得到的图像最终也需要复制到 IplImage 图像中,所以只需要一次内存操作        // 创建一个 IplImage 中间图像并直接使用 FreeImage 的图像,然后创建一个新的 IplImage 图像,        // 并把中间图像翻转到新 IplImage 中,然后关闭中间图像(只是头部结构)        IplImage* head cvCreateImageHeader(size, depth, channels);        cvSetData(head, data, head->widthStep); // 注意  widthStep 是能被 整除的数,为了整数对齐,加速运算        object_ptr spImage(new image(size, depth, (int) channels));// 智能数据对象指针,封装了IplImage        cvFlip(head, spImage->get_IplImage(), 0); // 翻转并复制 FreeImage 位图到 OpenCV 中        cvReleaseImageHeader(&head); // 释放 head,但不释放位图,因为位图是从 FreeImage 中“借”来的        m_images.push_back(adapt< object_ptr (spImage)); // 保存这个 IplImage 到 std::vector 中       if(bitmap_temp)        FreeImage_Unload(bitmap_temp);    }}当图像类型为 TIFF, ICO, GIF 时,可以使用 FreeImage 的多位图功能读出一组的图像,下面是使用 FreeImage 读取图像的代码片段:void zig_image_group::load_image(const char filename)    // 获取图像类型    FREE_IMAGE_FORMAT fif FIF_UNKNOWN;    if( FIF_UNKNOWN ==            (fif FreeImage_GetFileType(filename, 0))        fif FreeImage_GetFIFFromFilename(filename);       if( (fif == FIF_UNKNOWN) || FreeImage_FIFSupportsReading(fif)        // 使用 free image 不能打开影像,这时再尝试使用 opencv 打开影像        object_ptr sp_image(new image(filename, CV_LOAD_IMAGE_UNCHANGED));        if(sp_image->is_valid())            m_images.push_back(adapt< object_ptr >(sp_image));        else            cerr << "load image failure: << filename << endl;               return;       if (fif == FIF_TIFF || fif == FIF_ICO || fif == FIF_GIF)        // 读一组图像        FIMULTIBITMAP mdib                FreeImage_OpenMultiBitmap(fif, filename, false, true);        if(mdib)            int pages FreeImage_GetPageCount(mdib);            for(int page=0; page                FIBITMAP dib FreeImage_LockPage(mdib, page);                if(dib)                    load_bitmap(dib);                    FreeImage_UnlockPage(mdib, dib, false);                                      FreeImage_CloseMultiBitmap(mdib);           else        // 读一张图像        FIBITMAP dib FreeImage_Load(fif, filename);        if(dib)            load_bitmap(dib);            FreeImage_Unload(dib);           }}注意,以上代码中使用了类似于 ATL 的两个智能指针模板:object_ptr (类似于 atl::CComPtr), adapt (类似于 atl::CAdapt)。有了这两个智能指针模板,就可以方便地使用 STL 容器存放各种数据对象了。

http://hi.baidu.com/zighouse/item/b16d906d3a96c90ea1cf0fdf


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表