2011-02-07 15 views
6

En muchas funciones de trazado de MATLAB, puede especificar el color como una cadena o como un vector de 3 elementos que enumera directamente los valores de rojo, verde y azul.¿Cómo puedo convertir un nombre de color en un vector RGB de 3 elementos?

Por ejemplo, estas dos afirmaciones son equivalentes:

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

Hay 8 colores que se pueden especificar por un valor de cadena: 'r','g','b','c','m','y','k','w'. ¿Hay una función incorporada de MATLAB que convierta estas cadenas a un vector RGB equivalente?

Respuesta

6

me encontré con esta alternativa general sobre la MathWorks File Exchange que incluso manejar las cadenas de color que no sea el predeterminado 8 en MATLAB:

Si sólo estás preocupado con conversiones para las cadenas de 8 colores por defecto, aquí hay una función que escribí yo mismo que utilizo para convertir de ida y vuelta entre RGB triples y nombres de colores cortos (es decir, caracteres individuales):

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 

cuenta que esta función le permite introducir una cadena de caracteres o una matriz n-por-3 numérico o lógico (con valores RGB de 0 a 1 o de 0 a 255) y devuelve el representación de color opuesto. También usa la función ISMEMBER para realizar las conversiones.

+1

en realidad, si abre ismember.m, usa for-loops internamente para conjuntos pequeños y luego ordena los grandes conjuntos, por lo que no es obvio que sea más rápido; pero esto es agradable y probablemente más fácil de generalizar; también es un buen consejo en el rgb.m – Marc

+0

@Marc: Es cierto que si el rendimiento es crítico, es probable que desee escribir sus propios bucles para evitar cualquier sobrecarga adicional de la verificación de entrada y el formato que puede venir con ISMEMBER, pero cuando la velocidad no es t un problema ISMEMBER hace que el código sea más corto y fácil de leer. – gnovice

2

En caso de que no es, sólo corté una juntos

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 
+0

Obtuve los valores de CMYK de get (plot (x, y, 'Color', 'c'), 'Color')) etc. – Marc

+1

Puede evitar el uso de bucles for y cambiar declaraciones usando funciones como [ ISMEMBER] (http://www.mathworks.com/help/techdoc/ref/ismember.html) (ver [mi respuesta] (http://stackoverflow.com/questions/4922383/matlab-convert-color-name- to-rgb-3-element-vector/4923343 # 4923343) para un ejemplo). Además, sus advertencias tendrían más sentido como [errores] (http://www.mathworks.com/help/techdoc/ref/error.html). – gnovice

+1

En lugar de la instrucción 'exists', generalmente prefiero usar' if nargin <1' para verificar la existencia de la primera entrada, ya que 'exists' tiende a ser lenta (también hay menos tipeo). Además, creo que es posible que desee lanzar un error en lugar de una advertencia. – Jonas

4

No creo que hay una función para esto en MATLAB. Sugiero que use la función Marcs, o este one-liner.

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

muy lindo. Gracias. – Marc

+1

Aquí hay una aún más corta: 'C = bitget (find ('krgybmcw' == C) -1,1: 3);' – gnovice

Cuestiones relacionadas