使用FreeImage库读取gif彩色图像并将其转换为OpenCV Mat

使用FreeImage库读取gif彩色图像并将其转换为OpenCV Mat,opencv,opencv3.0,freeimage,Opencv,Opencv3.0,Freeimage,当我将Freeimage FIBITMAP*中的gif彩色图像从AT转换为OpenCV Mat时,颜色丢失。我使用opencv 3.1.0 我使用以下代码阅读A1.gif: FREE_IMAGE_FORMAT format = FreeImage_GetFileType(imgPath.c_str(), 0); FIBITMAP *image = FreeImage_Load(format, imgPath.c_str()); A1.gif 如果我用这段代码将图像转换为OpenCV Mat

当我将Freeimage FIBITMAP*中的gif彩色图像从AT转换为OpenCV Mat时,颜色丢失。我使用opencv 3.1.0

  • 我使用以下代码阅读A1.gif:

    FREE_IMAGE_FORMAT format = FreeImage_GetFileType(imgPath.c_str(), 0);
    FIBITMAP *image = FreeImage_Load(format, imgPath.c_str());
    
  • A1.gif

  • 如果我用这段代码将图像转换为OpenCV Mat并显示它,我会看到A2.jpg为什么OpenCV显示此图像而不是A1.gif?

    Mat img(FreeImage_GetHeight(image), FreeImage_GetWidth(image), CV_8UC3, FreeImage_GetBits(image), FreeImage_GetPitch(image));
    
    namedWindow("Display window", WINDOW_AUTOSIZE);
    imshow("Display window", img);
    
  • A2.jpg

  • 如果我将CV_8UC3更改为CV_8UC1,我会看到A3.jpg
  • A3.jpg

    对于jpg或tif等其他格式,问题不存在。解决方案是什么?

    Mat img(FreeImage_GetHeight(image), FreeImage_GetWidth(image), CV_8UC3, FreeImage_GetBits(image), FreeImage_GetPitch(image));
    
    namedWindow("Display window", WINDOW_AUTOSIZE);
    imshow("Display window", img);
    
    另一个例子是B1.gif、第二阶段分段错误和B3.jpg

    gif(我上传这张照片时,alpha频道似乎被删除了。)

    B3.gif

    我看到这两个帖子,但他们有相同的问题


    更新:我找到了解决方案

    使用FreeImage加载gif并将其转换为OpenCV Mat的正确代码:

    FIBITMAP *image = FreeImage_Load(format, GifImagePath);
    RGBQUAD *pal = FreeImage_GetPalette(image);
    unsigned width = FreeImage_GetWidth(image);
    unsigned height = FreeImage_GetHeight(image);
    
    FIBITMAP *tmp = FreeImage_Allocate(width, height, 24);
    BYTE *tmp_bits = FreeImage_GetBits(tmp);
    
    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            BYTE t;
    
            //FreeImage_GetPixelIndex(image,x, y, &t);//safer, in animated gif
            t = img_bits[x+y*height];//Probably faster
    
            RGBQUAD color = pal[t];
    
            //FreeImage_SetPixelColor(tmp, x, y, &color);//safer, in animated 
            //Probably faster
            tmp_bits[(x+y*height)*3 +FI_RGBA_RED] = color.rgbRed;
            tmp_bits[(x+y*height)*3+FI_RGBA_GREEN] = color.rgbGreen;
            tmp_bits[(x+y*height)*3+FI_RGBA_BLUE] = color.rgbBlue;
        }
    }
    
    Mat img(FreeImage_GetHeight(tmp), FreeImage_GetWidth(tmp), CV_8UC3, FreeImage_GetBits(tmp), FreeImage_GetPitch(tmp));
    
    namedWindow("Display window", WINDOW_AUTOSIZE);
    imshow("Display window", img);
    
    FIBITMAP*image=FreeImage\u加载(格式,GifImagePath);
    RGBQUAD*pal=FreeImage\u getpalete(图像);
    无符号宽度=FreeImage\u GetWidth(图像);
    无符号高度=FreeImage\u GetHeight(图像);
    FIBITMAP*tmp=FreeImage_分配(宽度、高度、24);
    字节*tmp_位=自由图像_获取位(tmp);
    对于(int y=0;y
    问题在于您没有正确处理图像-对您有问题的图像有两个共同点:

    • 他们脸色苍白,而且

    • 它们有一个alpha

    由于它们是调色板,位图中的数字并不表示颜色,它们表示调色板中的索引。我不使用,也不知道,FreeImage,但您需要获得调色板,然后迭代位图,而不是从位图中获取值并将其放入
    Mat
    ,您需要使用位图中的值作为调色板中的索引,并在指定的偏移量处获取颜色,然后将其放入
    Mat
    。可能有一个
    ConvertToType()
    类函数可以为您执行此操作-在这种情况下,您需要将调色板类型转换为真彩色类型

    其次,你需要处理透明度问题。如果您的图像具有透明度,则在OpenCV中需要一个4通道
    Mat
    ,它具有B、G、R和Alpha/透明度

    相比之下,JPEG图像不包含调色板,也不包含透明度-因此它们在代码中工作:-)

    如果您在Linux上,您将安装ImageMagick,并且您可以很容易地在macOS和Windows上获得它-它是免费的。然后,您可以查看您的图像,了解我的意思:

    identify -verbose drummer.gif | more
    
    输出

    Image: drummer.gif
      Format: GIF (CompuServe graphics interchange format)
      Mime type: image/gif
      Class: PseudoClass
      Geometry: 800x600+0+0
      Units: Undefined
      Type: PaletteAlpha             <--- Palette and transparency
      Endianess: Undefined
      Colorspace: sRGB
      Depth: 8-bit
      Channel depth:
        Red: 8-bit
        Green: 8-bit
        Blue: 8-bit
        Alpha: 1-bit                 <--- 4th transparency layer
    


    啊。。ImageMagick。。所有问题的解决方案;)@Miki Nah,曾经有一个答案是我必须使用Perl。和一个GNU并联;-)@Miki你知道合适的freeimage转换函数吗?@Iman不,我刚才写了一个(你已经看到了,因为它在你的问题中有链接)。。。它不应该适用于所有边缘情况。但是,您可以在此基础上创建自己的函数,添加缺少的代码来处理此情况。@MarkSetchell谢谢。我会检查你的解决方案。@MarkSetchell是的。你的答案是正确的,但我起初无法用FreeImage实现它,现在我设法做到了。
    convert drummer.gif drummer.jpg