【问题标题】:How can I convert a color name to a 3 element RGB vector?如何将颜色名称转换为 3 元素 RGB 矢量?
【发布时间】:2011-06-22 18:49:21
【问题描述】:

在许多 MATLAB 绘图函数中,您可以将颜色指定为字符串或直接列出红色、绿色和蓝色值的 3 元素向量。

例如,这两个语句是等价的:

plot(x, y, 'Color', 'r');
plot(x, y, 'Color', [1 0 0]);

可以通过字符串值指定 8 种颜色:'r','g','b','c','m','y','k','w'。是否有 MATLAB 内置函数可以将这些字符串转换为等效的 RGB 向量?

【问题讨论】:

    标签: matlab colors rgb


    【解决方案1】:

    我在MathWorks File Exchange 上找到了这个通用替代方案,它甚至可以处理 MATLAB 中默认 8 以外的颜色字符串:

    如果您只关心默认 8 种颜色字符串的转换,这是我自己编写的一个函数,用于在 RGB 三元组和短颜色名称(即单个字符)之间来回转换:

    function outColor = convert_color(inColor)
    
      charValues = 'rgbcmywk'.';  %#'
      rgbValues = [eye(3); 1-eye(3); 1 1 1; 0 0 0];
      assert(~isempty(inColor),'convert_color:badInputSize',...
             'Input argument must not be empty.');
    
      if ischar(inColor)  %# Input is a character string
    
        [isColor,colorIndex] = ismember(inColor(:),charValues);
        assert(all(isColor),'convert_color:badInputContents',...
               'String input can only contain the characters ''rgbcmywk''.');
        outColor = rgbValues(colorIndex,:);
    
      elseif isnumeric(inColor) || islogical(inColor)  %# Input is a numeric or
                                                       %#   logical array
        assert(size(inColor,2) == 3,'convert_color:badInputSize',...
               'Numeric input must be an N-by-3 matrix');
        inColor = double(inColor);           %# Convert input to type double
        scaleIndex = max(inColor,[],2) > 1;  %# Find rows with values > 1
        inColor(scaleIndex,:) = inColor(scaleIndex,:)./255;  %# Scale by 255
        [isColor,colorIndex] = ismember(inColor,rgbValues,'rows');
        assert(all(isColor),'convert_color:badInputContents',...
               'RGB input must define one of the colors ''rgbcmywk''.');
        outColor = charValues(colorIndex(:));
    
      else  %# Input is an invalid type
    
        error('convert_color:badInputType',...
              'Input must be a character or numeric array.');
    
      end
    

    请注意,此函数允许您输入字符串 N×3 数字或逻辑数组(RGB 值从 0 到 1 或 0 到 255)并返回相反的颜色表示。它还使用函数ISMEMBER 进行转换。

    【讨论】:

    • 其实,如果你打开ismember.m,它内部使用for-loops来处理小集合,然后对大集合进行排序,所以速度不是很明显;但这很好,可能更容易概括;在 rgb.m 上也有很好的提示
    • @Marc:是的,如果性能很关键,您可能希望编写自己的循环以避免使用 ISMEMBER 可能带来的输入检查和格式化的任何额外开销,但是当速度不是时问题 ISMEMBER 使代码更短且易于阅读。
    【解决方案2】:

    我认为 matlab 中没有此功能。我建议你使用 Marcs 函数,或者这个 one-liner。

    C = rem(floor((strfind('kbgcrmyw', C) - 1) * [0.25 0.5 1]), 2); 
    

    【讨论】:

    • 这里有一个更短的:C = bitget(find('krgybmcw'==C)-1,1:3);
    【解决方案3】:

    如果没有,我只是一起破解了一个

    function rgbvec = char2rgb (charcolor)
    %function rgbvec = char2rgb (charcolor)
    %
    %converts a character color (one of 'r','g','b','c','m','y','k','w') to a 3
    %value RGB vector
    %if charcolor is a string (vector of chars), the result is a Nx3 matrix of
    %color values, where N is the length of charcolor
    
    if (~exist(charcolor,'var') || ~ischar(charcolor))
        warning('RGB2VEC:NOTC', 'You must pass a character (rgbcmykw)');
        rgbvec = [0 0 0];
        return;
    end
    rgbvec = zeros(length(charcolor), 3);
    charwarning = false;
    for j = 1:length(charcolor)
        switch(lower(charcolor(j)))
            case 'r'
                rgbvec(j,:) = [1 0 0];
            case 'g'
                rgbvec(j,:) = [0 1 0];
            case 'b'
                rgbvec(j,:) = [0 0 1];
            case 'c'
                rgbvec(j,:) = [0 1 1];
            case 'm'
                rgbvec(j,:) = [1 0 1];
            case 'y'
                rgbvec(j,:) = [1 1 0];
            case 'w'
                rgbvec(j,:) = [1 1 1];
            case 'k'
                rgbvec(j,:) = [0 0 0];
            otherwise
                charwarning = true;
        end
    end
    
    if (charwarning)
        warning('RGB2VEC:BADC', 'Only r,g,b,c,m,y,k,and w are recognized colors');
    end
    

    【讨论】:

    • 我从 get(plot(x,y,'Color','c'), 'Color')) 等中得到了 cmyk 值。
    • 您实际上可以通过使用 ISMEMBER 之类的函数来避免使用 for 循环和 switch 语句(示例参见 my answer)。此外,您的警告将更有意义errors
    • 我通常更喜欢使用if nargin < 1 来检查第一个输入是否存在,而不是exist 语句,因为exist 往往很慢(而且打字也更少)。另外,我认为您可能想抛出错误而不是警告。
    【解决方案4】:

    这是一个你不必为 C 解决的单行:

    str2rgb=@(x)get(line('color',x),'color');
    

    现在str2rgb 给你答案。例如str2rgb('c') = [0 1 1]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-24
      • 2012-03-30
      • 2017-10-28
      • 2010-09-26
      • 2011-08-25
      • 1970-01-01
      • 2019-02-08
      • 2018-11-14
      相关资源
      最近更新 更多