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

使用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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值