【问题标题】:How to read an animated gif with alpha channel如何读取带有 Alpha 通道的动画 gif
【发布时间】:2016-04-30 10:22:14
【问题描述】:

在 MATLAB 中对 .gif 动画进行一些测试时,我意识到不知何故我无法读取 gif 的透明度。

例子:

(Original source of the gif)

如果我这样做了

[img,cmap]=imread('Finnandjake.gif');

img 是 4D,具有冗余的第 3 维(奇怪)。挤压后(img=squeeze(img);),如果我显示它(imshow(img(:,:,30),cmap)):

透明度消失了,使用图像中的另一种颜色作为背景,从而删除了特征。不过

[img,cmap,alpha]=imread('Finnandjake.gif');

返回一个空的alpha。很明显alpha的信息在某处的图像中,我如何在MATLAB中读取它?

【问题讨论】:

  • 我认为 matlab 无法管理 .gif 图像的透明度。来自 mathworks.com:imread(___) additionally returns the image transparency. This syntax applies only to PNG, CUR, and ICO files.
  • @obchardon 我注意到了,但是,有没有办法用 alpha 信息将 gif 文件加载到 MATLAB?它只是一个gif文件,它不会那么难
  • 我想建议使用 Imagemagick 将 GIF 转换为 PNG 并循环读取 PNG。但我什至无法让 MATLAB 识别 PNG 中的 Alpha 层,尽管它 is 存在于文件中。 :-(
  • @Daniel,但这很奇怪,因为 .gif 的第一帧为透明区域提供 53,最后一帧为 0...没有一致性。因此,对于第一帧,您可以修改 cmap。 cmap(53:end,:) == 1; 但是对于最后一帧它不起作用。
  • 使用图像进行测试here 似乎表明 Matlab 要么存在错误,要么不支持功能,要么与大多数常见的 GIF 解析器不同。

标签: image matlab gif alpha


【解决方案1】:

/更新:我在MATLAB file exchange 提供了代码。已发布的版本与 OCTAVE 兼容,并附带一些文档。


我想出了这个解决方案。返回参数是堆叠的图像、颜色图和透明度对应的索引。

%do not use, instead use: http://www.mathworks.com/matlabcentral/fileexchange/55693-transparentgifread-filename-
function [stack,map,transparent]=transparentGifRead(filename)
if ~exist(filename,'file')
    error('file %s does not exist',filename);
end
info=imfinfo(filename);
%Check if color map for all frames is the same
if any(any(any(diff(cat(3,info.ColorTable),[],3))))
    error('inconsistent color map')
else
    map=info(1).ColorTable;
end
%Check if transparent color for all frames is the same
if any(diff([info.TransparentColor]))
    error('inconsistent transparency information')
else
    transparent=info(1).TransparentColor-1;
end
import java.io.*
str = javax.imageio.ImageIO.createImageInputStream(java.io.File(filename));
t = javax.imageio.ImageIO.getImageReaders(str);
reader = t.next();
reader.setInput(str);
numframes = reader.getNumImages(true);
for imageix = 1:numframes
    data = reader.read(imageix-1).getData();
    height = data.getHeight();
    width = data.getWidth();
    data2 = reader.read(imageix-1).getData().getPixels(0,0,width,height,[]);
    if imageix == 1
        stack=zeros(height,width,1,numframes,'uint8');
    end
    %row major vs column major fix
    stack(:,:,1,imageix) = reshape(data2,[width height]).';%'
end
str.close();
end

一些将透明像素着色为绿色的演示代码:

[stack,map,transparent]=transparentGifRead('tr.gif');
map(transparent+1,:)=[0,1,0] %offset 1 because uint8 starts at 0 but indices at 1
for frame=1:size(stack,ndims(stack))
    imshow(stack(:,:,frame),map);
    pause(1/25);
end

【讨论】:

  • 两个问题:x=fullfile(matlabroot,'toolbox\matlab\imagesci','private','imgifinfo.m'); 应该是 x=fullfile(matlabroot,'toolbox','matlab','imagesci','private','imgifinfo.m'); 才能跨平台工作。此外,您似乎在将图像数据索引到颜色图中时遇到了一个错误。
  • @horchler:感谢您的反馈,只是比较了值,并没有意识到我的函数返回双精度值而不是 uint8。现在它返回 uint8,颜色图和整数值之间的偏移量是 1。
  • 您应该能够使用info = iminfo(filename); 来获取每个帧的TransparentColor 属性等详细信息,而无需调用私有函数。
  • @AnderBiguri:使用 uint8 时,地图从索引 1 开始,但图像从索引 0 开始,偏移量为 1。正确的代码是 map(transparent+1,:)=1,请参阅我末尾的示例回答。
  • @Daniel 是的,这绝对是它!感谢您的努力!
猜你喜欢
  • 2014-11-22
  • 2023-03-23
  • 2016-04-03
  • 1970-01-01
  • 2011-09-06
  • 1970-01-01
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多