2011-02-07 4 views
6

In molte funzioni di disegno MATLAB, è possibile specificare il colore come stringa o come vettore di 3 elementi che elenca direttamente i valori rosso, verde e blu.Come posso convertire un nome di colore in un vettore RGB a 3 elementi?

Ad esempio, queste due istruzioni sono equivalenti:

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

ci sono 8 colori che possono essere specificati da un valore di stringa: 'r','g','b','c','m','y','k','w'. Esiste una funzione incorporata di MATLAB che converte queste stringhe in un vettore RGB equivalente?

risposta

6

Ho trovato questa alternativa generale sulla MathWorks File Exchange che sarà anche di gestire stringhe di colore diversi da quello di default 8 in MATLAB:

Se sei preoccupato solo con le conversioni per le stringhe di 8 colori predefinite, ecco una funzione che ho scritto io stesso che uso per convertire avanti e indietro tra tripli RGB e nomi di colori corti (cioè singoli caratteri):

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 

noti che questa funzione consente di immettere una stringa di caratteri o una matrice N-per-3 numerico o logico (RGB con valori da 0 a 1 o 0 a 255) e restituisce la rappresentazione a colori opposta. Utilizza anche la funzione ISMEMBER per eseguire le conversioni.

+1

in realtà, se si apre ismember.m, utilizza for-loops internamente per piccoli set e poi ordina i set di grandi dimensioni, quindi non è ovvio che sia più veloce; ma questo è bello e probabilmente più facile da generalizzare; anche un buon consiglio su rgb.m – Marc

+0

@Marc: è vero, se le prestazioni sono critiche, probabilmente vorrai scrivere i tuoi loop per evitare ulteriori sovraccarichi dal controllo degli input e dalla formattazione che potrebbero derivare dall'uso di ISMEMBER, ma quando la velocità non è t un problema ISMEMBER rende il codice più breve e facile da leggere. – gnovice

2

Nel caso in cui non c'è, ho appena hackerato un insieme

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

Ho ottenuto i valori di cmyk da get (grafico (x, y, 'Colore', 'c'), 'Colore')) che ecc. – Marc

+1

È possibile evitare di utilizzare per cicli e passare istruzioni utilizzando funzioni come [ ISMEMBER] (http://www.mathworks.com/help/techdoc/ref/ismember.html) (vedi [risposta] (http://stackoverflow.com/questions/4922383/matlab-convert-color-name- to-rgb-3-element-vector/4923343 # 4923343) per un esempio). Inoltre, i tuoi avvertimenti avrebbero più senso come [errori] (http://www.mathworks.com/help/techdoc/ref/error.html). – gnovice

+1

Invece dell'istruzione 'exist', generalmente preferisco usare' if nargin <1' per verificare l'esistenza del primo input, poiché 'exist' tende a essere lento (inoltre, c'è meno digitamento). Inoltre, penso che potresti voler lanciare un errore invece di un avvertimento. – Jonas

4

Non credo che ci sia una funzione per questo in MATLAB. Ti suggerisco di usare la funzione Marcs o questa one-liner.

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

molto carino. Grazie. – Marc

+1

Ecco un ancora più breve: 'C = bitget (find ('krgybmcw' == C) -1,1: 3);' – gnovice