2011-01-15 11 views
11

Come posso ottenere questo tipo di sostituzione del colore a livello di programmazione? replacing black with blueCome ricolorare un'immagine? (vedi immagini)


Quindi questa è la funzione che ho utilizzato per sostituire un pixel:

Color.FromArgb(
    oldColorInThisPixel.R + (byte)((1 - oldColorInThisPixel.R/255.0) * colorToReplaceWith.R), 
    oldColorInThisPixel.G + (byte)((1 - oldColorInThisPixel.G/255.0) * colorToReplaceWith.G), 
    oldColorInThisPixel.B + (byte)((1 - oldColorInThisPixel.B/255.0) * colorToReplaceWith.B) 
    ) 

Grazie, CodeInChaos!

+1

Perché perdo un upvote, o ottenere un downvote? lol ... – Vercas

+1

Nessun downvotes. Presumo che qualcuno sia stato in grado di rimuovere il loro upvote quando hai modificato la domanda. In ogni caso, non è qualcosa che vale la pena di preoccuparsi a meno che qualcuno non lasci un commento con un suggerimento o una critica specifica. :-) –

risposta

8

La formula per calcolare la nuovo pixel è:

newColor.R=OldColor; 
newColor.G=OldColor; 
newColor.B=255; 

Generalizzazione al colo arbitrario rs:

Suppongo che si desideri mappare il bianco con il bianco e il nero con quel colore. Così la formula è newColor=TargetColor+(White-TargetColor)*Input

newColor.R=OldColor+(1-oldColor/255.0)*TargetColor.R; 
newColor.G=OldColor+(1-oldColor/255.0)*TargetColor.G; 
newColor.B=OldColor+(1-oldColor/255.0)*TargetColor.B; 

E poi basta scorrere i pixel dell'immagine (matrice di byte) e scrivere in un nuovo array RGB. Ci sono molti thread su come copiare un'immagine in una matrice di byte e manipolarla.

+0

Questa risposta sembra la migliore per me, ma quel blu potrebbe essere di qualsiasi colore. – Vercas

+0

@Vercas Aggiunta formula per colori arbitrari. – CodesInChaos

+1

@CodeInChaos Sto testando la formula ora. Inoltre, hai dimenticato di aggiungere .R, .G e .B alla variabile "oldColor". – Vercas

2

Questo articolo del progetto di codice copre questo e molto altro: http://www.codeproject.com/KB/GDI-plus/Image_Processing_Lab.aspx

utilizza la libreria AForge.NET di fare un filtro Hue su un'immagine per un effetto simile:

// create filter 

    AForge.Imaging.Filters.HSLFiltering filter = 
     new AForge.Imaging.Filters.HSLFiltering(); 
    filter.Hue = new IntRange(340, 20); 
    filter.UpdateHue = false; 
    filter.UpdateLuminance = false; 
    // apply the filter 

    System.Drawing.Bitmap newImage = filter.Apply(image); 
+0

Quindi, cambierà qualsiasi colore dell'intervallo con il mio colore? – Vercas

+0

Sì, l'intervallo di tonalità sembra strano ... la tonalità dovrebbe normalmente essere un valore singolo, no? – Nyerguds

+0

Credo che la libreria utilizzi un intervallo di tonalità per consentire una facile sostituzione dei colori sulle immagini acquisite con una fotocamera. Pensa allo schermo verde, il verde non è uniforme nell'immagine, ma rientra nell'intervallo in base alle ombre, ecc. –

3

dipende molto ciò che la vostra immagine sul il formato è e quale sarà il tuo formato finale.

Dipende anche dallo strumento che si desidera utilizzare. È possibile utilizzare:

  • GDI
  • GD +
  • libreria di elaborazione immagini come OpenCV

GDI è abbastanza veloce, ma può essere molto ingombrante. Devi cambiare la tavolozza. GDI + è esposto in .NET e può essere più lento ma più semplice. OpenCV è ottimo ma aggiunge dipendenza.


(AGGIORNAMENTO)

Questo codice modifica l'immagine di blu-scale invece di scale di grigio - formato immagine è 32 bit ARGB:

private static unsafe void ChangeColors(string imageFileName) 
{ 
    const int noOfChannels = 4; 
    Bitmap img = (Bitmap) Image.FromFile(imageFileName); 
    BitmapData data = img.LockBits(new Rectangle(0,0,img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat); 
    byte* ptr = (byte*) data.Scan0; 
    for (int j = 0; j < data.Height; j++) 
    { 
     byte* scanPtr = ptr + (j * data.Stride); 
     for (int i = 0; i < data.Stride; i++, scanPtr++) 
     { 
      if (i % noOfChannels == 3) 
      { 
       *scanPtr = 255; 
       continue; 
      } 
      if (i % noOfChannels != 0) 
      { 
       *scanPtr = 0; 
      } 
     } 
    } 

    img.UnlockBits(data); 
    img.Save(Path.Combine(Path.GetDirectoryName(imageFileName), "result.png"), ImageFormat.Png); 
} 
+0

'System.Drawing.Image' è il mio formato immagine. :) – Vercas

+0

Sì, amico mio, ma ImageFormat è importante. È una scala di grigi a 8 bit? Bitmap WIndows a 24 bit? 32 bit con alfa? Se mi dici quale vuoi usare, posso darti l'esempio di codice. – Aliostad

+0

Bene, sto aprendo un'immagine PNG senza trasparenza, quindi suppongo sia 24 bit. – Vercas

1

Dipende anche da ciò che si desidera: si desidera mantenere l'originale e regolare solo il modo in cui viene visualizzato? Un effetto o pixelhader in WPF potrebbe fare il trucco ed essere molto veloce.

+0

No, ho bisogno di regolare l'originale. – Vercas

9

Il più semplice sarebbe utilizzare ColorMatrix per l'elaborazione delle immagini, sarete anche in grado di elaborare al volo l'anteprima dell'effetto desiderato - questo è il numero di filtri colorati creati nelle applicazioni di modifica grafica. Here e here puoi trovare le introduzioni agli effetti cromatici usando Colormatrix in C#.Utilizzando ColorMatrix è possibile effettuare colorazione filtro come vuoi tu, così come seppia, bianco/nero, invertito, gamma, luminosità, contrasto, luminosità, livelli (da multi-pass), ecc

EDIT: Ecco esempio (aggiornamento - matrice colore fisso di spostare i valori più scuri in blu invece dei precedenti azzeramento diverso da parti blu - e - 0.5f aggiunto al blu perché sulla foto sopra nero è trasformata in 50% blu):

var cm = new ColorMatrix(new float[][] 
{ 
    new float[] {1, 0, 0, 0, 0}, 
    new float[] {0, 1, 1, 0, 0}, 
    new float[] {0, 0, 1, 0, 0}, 
    new float[] {0, 0, 0, 1, 0}, 
    new float[] {0, 0, 0.5f, 0, 1} 
}); 

var img = Image.FromFile("C:\\img.png"); 
var ia = new ImageAttributes(); 
ia.SetColorMatrix(cm); 

var bmp = new Bitmap(img.Width, img.Height); 
var gfx = Graphics.FromImage(bmp); 
var rect = new Rectangle(0, 0, img.Width, img.Height); 

gfx.DrawImage(img, rect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia); 

bmp.Save("C:\\processed.png", ImageFormat.Png); 
+0

Potrei usare una matrice di colori, ma non ho idea di cosa sia e come usarlo per il mio scopo. – Vercas

+0

L'esempio sopra fa esattamente ciò che la conversione dell'immagine di esempio sopra. – too

+0

Puoi sperimentare con i valori, nell'ultima riga 3 valori stanno aggiungendo valori RGB (valore da -1 a 1 significa valore da -255 a 255), su diagonale sono moltiplicazioni di valori RGB originali (se moltiplichi/aggiungi troppo, pixel il valore sarà 0 o 255), vicino alla diagonale ho impostato 1 per spostare i valori in blu. Sperimenta, ne vale la pena. – too

4

Avrete vuoi usare ColorMatrix qui. L'immagine sorgente è in scala di grigi, tutti i suoi valori R, G e B sono uguali. Quindi si tratta semplicemente di sostituire il nero con RGB = (0, 0, 255) per il blu scuro, bianco con RGB = (255, 255, 255) per ottenere il bianco. La matrice così può apparire come questo:

1 0 0 0 0  // not changing red 
0 1 0 0 0  // not changing green 
0 0 0 0 0  // B = 0 
0 0 0 1 0  // not changing alpha 
0 0 1 0 1  // B = 255 

Questo modulo di esempio riproduce l'immagine a destra:

public partial class Form1 : Form { 
    public Form1() { 
     InitializeComponent(); 
    } 
    private Image mImage; 
    protected override void OnPaint(PaintEventArgs e) { 
     if (mImage != null) e.Graphics.DrawImage(mImage, Point.Empty); 
     base.OnPaint(e); 
    } 
    private void button1_Click(object sender, EventArgs e) { 
     using (var srce = Image.FromFile(@"c:\temp\grayscale.png")) { 
      if (mImage != null) mImage.Dispose(); 
      mImage = new Bitmap(srce.Width, srce.Height); 
      float[][] coeff = { 
          new float[] { 1, 0, 0, 0, 0 }, 
          new float[] { 0, 1, 0, 0, 0 }, 
          new float[] { 0, 0, 0, 0, 0 }, 
          new float[] { 0, 0, 0, 1, 0 }, 
          new float[] { 0, 0, 1, 0, 1 }}; 
      ColorMatrix cm = new ColorMatrix(coeff); 
      var ia = new ImageAttributes(); 
      ia.SetColorMatrix(new ColorMatrix(coeff)); 
      using (var gr = Graphics.FromImage(mImage)) { 
       gr.DrawImage(srce, new Rectangle(0, 0, mImage.Width, mImage.Height), 
        0, 0, mImage.Width, mImage.Height, GraphicsUnit.Pixel, ia); 
      } 
     } 
     this.Invalidate(); 
    } 
} 
+0

Quel blu era solo un esempio. L'immagine da ricolorare può avere qualsiasi colore, non solo in scala di grigi e il colore da sostituire/aggiungere può essere di qualsiasi colore, il che significa che R, G e B possono essere qualsiasi cosa. Non capisco affatto queste matrici di colori. – Vercas

+1

Bene, questo è solo un esempio di come si usa ColorMatrix per sostituire i colori. Dovrai inventare i tuoi coefficienti per fare la tua sostituzione. Utilizzare questo tutorial per avere un'idea di come funziona: http://active.tutsplus.com/tutorials/effects/manipulate-visual-effects-with-the-colormatrixfilter-and-convolutionfilter/ –

0

Se alcuni sviluppatori Android finiscono per guardare a questo, questo è quello che mi è venuta al grigio ridimensionare e colorare un'immagine utilizzando la formula di CodesInChaos e le classi di grafica Android ColorMatrix e ColorMatrixColorFilter.

Grazie per l'aiuto!

public static ColorFilter getColorFilter(Context context) { 
    final int tint = ContextCompat.getColor(context, R.color.tint); 

    final float R = Color.red(tint); 
    final float G = Color.green(tint); 
    final float B = Color.blue(tint); 

    final float Rs = R/255; 
    final float Gs = G/255; 
    final float Bs = B/255; 

    // resultColor = oldColor + (1 - oldColor/255) * tintColor 
    final float[] colorTransform = { 
      1, -Rs, 0, 0, R, 
      1, -Gs, 0, 0, G, 
      1, -Bs, 0, 0, B, 
      0, 0, 0, 0.9f, 0}; 

    final ColorMatrix grayMatrix = new ColorMatrix(); 
    grayMatrix.setSaturation(0f); 
    grayMatrix.postConcat(new ColorMatrix(colorTransform)); 
    return new ColorMatrixColorFilter(grayMatrix); 
} 

Il ColorFilter può quindi essere applicato a un ImageView

imageView.setColorFilter(getColorFilter(imageView.getContext())); 
Problemi correlati