Matlab:检查目录中的所有图像是否为灰度图像?

3

我想检查当前目录中的所有jpg图片是否为灰度图像或包含彩色像素... 我尝试了:

figdirectory = pwd;
fullpath = sprintf('%s/*.jpg', figdirectory);
d = dir(fullpath);

% Loop
pages = [];
for i = 1:length(d)
    f = d(i).name;
    fname_input = sprintf('%s/%s', figdirectory, f);

    A = imread(fname_input); 
    B = rgb2gray(A);

    if(A-B == 0)
        hascolor = 0;
    else
        hascolor = 1;
    end
    pages = [pages; hascolor];        
end 

但是这让我在A和B的矩阵维度上出现了错误。为什么A有第三个维度呢?谢谢!

4个回答

4
为了做到这一点:
0) 假设输入的东西只是“图像”,而不是“卷积”。
1) [r c d] = size(im);
2) 如果d大于1,则这是一个彩色图像。
3) 否则,它必须是灰度图像。
编辑:
您可以添加一个条件来确定灰度图像和彩色图像。 假设您的彩色图像有3个通道,
如果d等于3,则检查所有3个通道是否相等
im(:,:,1)==im(:,:,2) && im(:,:,1)==im(:,:,3) 然后您将拥有灰度图像,否则为彩色图像

谢谢。我修改了代码为A = imread(fname_input); [r c e] = size(A); if(e > 1) hascolor = 1; else hascolor = 0; end,但它不起作用:灰度图像也被识别为彩色图像 :( - tim
这是一本书中的彩色扫描吗?因此被识别为彩色图像。 - Adrian
1
@col Heather,关于颜色图像的另一个定义是每个像素在红绿蓝三个通道中的值都相同。请查看我回答的补充部分。 - Gary Tsui

2
从imread的手册中http://www.mathworks.co.uk/help/techdoc/ref/imread.html
如果文件包含灰度图像,则A是一个M×N数组。如果文件包含真彩色图像,则A是一个M×N×3数组。
因此,对于彩色图像,A将具有第三个维度。
如果您想测试灰度图像,则可以将图像转换为hsv。
B = rgb2hsv(A)

从手册中,http://www.mathworks.co.uk/help/techdoc/ref/hsv2rgb.html 当B(:,2)为0时,颜色是不饱和的(即灰色阴影)。
对于像发布的真彩色图像这样的情况,如果unique(B(:,:,2))为零,则会出现这种情况。
A = imread(fname_input);        
B = rgb2hsv(A);

%# if saturation levels are zero then it's a greyscale image
if(unique(B(:,:,2)) == 0)
    hascolor = 0;
else         
    hascolor = 1; 
end 

2
您可以使用 IMFINFO 来完成这个任务,这样您就不必将图像加载到内存中。
figdirectory = pwd;
fullpath = sprintf('%s/*.jpg', figdirectory);
d = dir(fullpath);

nImages = length(d);

%# imageType is a cell array with either 'grayscale', 'truecolor', or 'indexed', 
%# depending on the kind of image you have. 

imageType = cell(nImages,1);

for iImg = 1:nImages
info = imfinfo(d(iImg).name);
imageType{iImg} = info.ColorType;
end

%# isGrayscale is true for grayscale images, false otherwise 
%# (though note that there might be mapped images that map to a grayscale colormap).
isGrayscale = cellfun(@(x)strcmp(x,'grayscale'),imageType);

EDIT

%# the indexed images have to be loaded in order for you to check 
%# for grayscale maps

indexedIdx = find(cellfun(@(x)strcmp(x,'indexed'),imageType));

for iImg = indexedIdx(:)'

   [~,map] = imread(fullfile(figDirectory,d(iImg).name));

   %# It's a grayscale image if rgb map values are all equal
   isGrayscale(iImg) = all(all(bsxfun(@eq,map,map(:,1)),2),1);
end

%# finally, it is possible that the images are *stored* as truecolor
%# but containing, in fact, a grayscale image

truecolorIdx = find(cellfun(@(x)strcmp(x,'truecolor'),imageType));

for iImg = truecolorIdx(:)'

   img = imread(fullfile(figDirectory,d(iImg).name));

   %# It's a grayscale image if rgb map values are all equal
   isGrayscale(iImg) = all(all(all(bsxfun(@eq,img(:,:,1),img),1),2),3);
end

如何处理这个灰度图?我在第一篇帖子中上传了一张灰度图片,但你的代码没有正确处理它! - tim
@Col Heather:你必须加载图像才能获取地图,然后可以检查它是彩色还是灰度。请看我的编辑。 - Jonas
@Col Heather:另外,如果图像以真彩色格式存储,但实际上只包含灰度信息,则需要实际加载该图像。 - Jonas
对于提供的示例,由于它是真彩色图像,我认为imread不会返回一个颜色映射进行处理。正如我在回复中更新的那样,我认为将其转换为HSV并检查饱和度水平会更容易,对于灰度图像,这将为零。 - Adrian

2

这里有一个基于IMFINFO的简单解决方案:

%# some test images shipped with the Image Processing Toolbox
fNames = {
    'circles.png'   %# binary
    'shadow.tif'    %# indexed color
    'coins.png'     %# gray
    'peppers.png'   %# RGB
};

isGrayscale = false(size(fNames));
for i=1:numel(fNames)
    imgInfo = imfinfo(fNames{i});
    if strcmp(imgInfo.ColorType,'truecolor')
        isGrayscale(i) = false;
    elseif strcmp(imgInfo.ColorType,'grayscale')
        isGrayscale(i) = true;
    elseif strcmp(imgInfo.ColorType,'indexed')
            %# indexed images colormap (the three channels should be all same)
        isGrayscale(i) = all(all( diff(imgInfo.Colormap,[],2)==0 ,2),1);
    end
end

你的情况中第一部分可以是:

dirName = 'C:\path\to\myimages';
files = dir( fullfile(dirName,'*.jpg') );
fNames = {files.name}';

编辑:

@Adrian:关于你提供的图片,就保存的格式而言,它是彩色图片。现在所有颜色通道都相同这一事实只是一个特例...

无论如何,如果你想要检测这种情况,将上述代码中的'truecolor'部分更改为:

#% ...
if strcmp(imgInfo.ColorType,'truecolor')
    img = imread(fNames{i});
    isGrayscale(i) = isequal(img(:,:,1),img(:,:,2),img(:,:,3));
elseif strcmp(imgInfo.ColorType,'grayscale')
#% ...

你尝试过在问题附带的示例图像上运行吗?这似乎是一张来自书页的彩色扫描或图片。虽然页面是黑白的,但扫描的图像实际上被识别为真彩色图像。 - Adrian
@Adrian:请看我的上面回复。 - Amro
只是澄清一下,提供的图像是由Col添加的,而不是我自己。虽然我认为您的代码可能更能处理不同类型的图像,但如果目录中的所有图像都是来自书籍的扫描图像并且是真彩色,则我仍然更喜欢我的HSV解决方案,因为我认为它可以提供更清晰和更易读的代码。谢谢。 - Adrian
1
首先,如果所有图像都已知为一种类型,则问题将不存在!其次,您说您的代码更易读,但您尚未处理所有情况:如果图像被索引,则必须加载颜色映射表,转换为完整的RGB,然后继续解决方案。最后,我的“真彩色”版本(加载图像并检查R==G==B)比转换为HSV然后检查S是否全为零要快得多。根据定义,饱和度是从C=max(R,G,B)-min(R,G,B)计算的,如果C==0,则S=0。因此,通过简单地检查所有通道是否相等,我们避免了很多额外的工作... - Amro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接