Domanda

figure

Date le coordinate dei pixel neri, potrei interpolare i valori di coordinate del pixel blu attraverso l'equazione matematica y = mx + c. Ma per quanto riguarda i nuovi valori di pixel RGB? Come posso ottenere il valore RGB medio ponderato per i pixel blu dato che i valori RGB di pixel neri sono riportati come tali nella figura?

Ogni aiuto è molto apprezzato. Grazie in anticipo.

È stato utile?

Soluzione

Interpolare i valori in modo indipendente, eseguendo un calcolo ciascuno per R, G e B. Ad esempio, interpolando a metà strada tra (200,50,10) e (0,0,0) rendimenti (100,25,5).

Altri suggerimenti

(Questo potrebbe andare a lungo. Cercherò di mantenerlo breve, nel qual caso probabilmente dovrò tornare alla mia risposta per rispondere alle domande.) L'interpolazione dello spazio dei colori in RGB usa spesso l'interpolazione triinea, che può essere costruita sopra Una coppia di interpolazioni bilineari. Ma non è necessario che si utilizzi l'interpolazione trilineare. In effetti, altri interpolanti sono spesso migliori, ad esempio un interpolante semplici (o tetraedrico) è di solito preferito per una serie di ragioni rispetto a Trilineare. Esistono diverse dissezioni tetraedriche di un reticolo che si può usare. Uno è abbastanza standard. (Non entrerò troppo nei dettagli lì, almeno non ancora.) Inoltre, non c'è motivo per cui si debba interpolare in RGB invece di qualche altro spazio, anche se si potrebbe sostenere che RGB abbia i suoi problemi speciali, di solito in giro interpolazione di neutri e neutri vicini.

La caratteristica che è pertinente a RGB e l'interpolazione è che un neutro è definito come un punto tale che r = g = b. L'interpolante trilineare avrà il massimo errore lungo quell'asse neutro e di solito avrà una forma caratteristica (smerlata) per gli errori lungo il percorso neutro attraverso lo spazio colore.

Allora come possiamo interpolare in 3-D? Suppongo che uno si stia interpolando in un reticolo normale di punti nello spazio dei colori. In tal caso, si può identificare un cubo che contiene un singolo punto. Se stai interpolando all'interno di un insieme sparso di punti, la soluzione più semplice è di solito per costruire una triangolazione di tali punti, quindi fare un'interpolazione semplici (lineare) all'interno di un dato tetraedro. Gli interpolanti di ordine superiore sono comunque problematici qui, in quanto possono causare problemi di colore in alcune circostanze. Non si vorrebbe vedere le inversioni lungo i gradienti per esempio. Ciò potrebbe accadere dal momento che lo squillo è un grave problema con gli interpolanti basati su spline nelle regioni con curvatura relativamente elevata. E se c'è una mappatura della gamma coinvolta, tali transizioni saranno sicuramente un problema. Anche se non è necessaria alcuna mappatura di gamma, ci sono ancora problemi di gamma da affrontare.

Esistono diversi modi per costruire triangolazioni di domini da dati sparsi. Le forme alfa si basano su una triangolazione Delaunay e sono una scelta ragionevole. Ma supponendo che tu abbia un reticolo regolare e desideri fare un'interpolazione triinea, il problema si riduce all'interpolazione all'interno di un semplice cubo in 3-D.

Si noti che l'interpolazione triineare non è veramente un interpolante lineare, non più di quanto non sia l'interpolazione bilineare. Questi schemi sono lineari solo lungo gli assi del reticolo, ma lungo qualsiasi altro percorso attraverso lo spazio dei colori, hanno un carattere polinomiale. Pertanto, un interpolante triineare mostrerà un comportamento polinomiale cubico lungo la diagonale principale o lungo la maggior parte dei percorsi generali attraverso il cubo. Possiamo convincere noi stessi che l'interpolazione trilineare non è veramente lineare, poiché ci sono 8 punti tra cui interpolare. In 3-D, 4 punti determinano un interpolante veramente lineare, in funzione di quelle variabili indipendenti, ma abbiamo 8 punti che definiscono un cubo. Cioè, vedremo una mappatura da uno spazio RGB all'altro come 3 mappature indipendenti, quindi RGB -> UVW (ho scelto UVW qui per rappresentare un altro spazio di colore generico, che potrebbe o non può essere RGB nel personaggio .)

Il trucco è che costruiamo un interpolante triineare interpolando tra una coppia di interpolanti bilineari. Costruiamo quegli interpolanti bilineari interpolando linearmente tra una coppia di punti lungo un bordo e quindi facendo una terza interpolazione tra di loro. Quindi davvero, possiamo trattare un interpolante triineare come composto da 7 semplici interpolazioni lineari. È interessante notare che si può dimostrare che non importa quali assi facciamo per primi le interpolazioni. Possiamo prima interpolare lungo la R, quindi la B, quindi gli assi G o scegliere qualsiasi altro ordine: l'interpolante trilineare sarà unico e identico per qualsiasi ordine scelto. (Lo stesso vale per l'interpolante bilineare.)

Quindi il trucco è: come facciamo un'interpolazione lineare tra due triadi di punti? Innanzitutto, dobbiamo determinare dove sul segmento di linea tra quei punti che mentiamo. Ad esempio, considera due punti nel nostro spazio colore che si trovano lungo un bordo rosso (R) del cubo. Userò gli stessi valori che hai mostrato per quei punti, quindi:

Q1 = [66, 51, 77]
Q2 = [55, 66, 77]

Questi sono i valori che ci interpoleremo, essenzialmente l'output della nostra mappatura, ma dobbiamo anche sapere dove si trovano quei punti nello spazio RGB input. Quindi supponiamo che queste coordinate, basate sulle coordinate del cubo da cui provenivano, siano:

P1 = [0, 0, 0]
P2 = [1, 0, 0]

Questo è un cubo unitario in 3-D come l'ho scritto, quindi gli altri punti si troverebbero

P3 = [0, 1, 0]
P4 = [1, 1, 0]
P5 = [0, 0, 1]
P6 = [1, 0, 1]
P7 = [0, 1, 1]
P8 = [1, 1, 1]

Naturalmente, qualsiasi cubo generale funziona anche e non c'è motivo per essere un vero cubo. Qualsiasi prisma rettangolare a 4 lati rettangolari 3D funzionerà anche qui. Puoi sempre trasformare le cose nel cubo dell'unità.

Ora, supponiamo che desideriamo interpolare lungo questo bordo del cubo tra P1 e P2, nel dominio definito da Q1 e Q2? Scegli un certo punto lungo quel bordo. Puoi vedere che solo R varia lungo quel bordo tra questi punti, quindi ci preoccupiamo solo del valore di R nel punto in cui interpoliamo. Pensaci in termini di percentuale della distanza lungo il bordo. L'interpolazione è semplicemente una media ponderata dei due endpoint, una combinazione lineare. Quindi, per il punto con valore rosso di R lungo il bordo da 0 a 1 nel canale rosso, la nostra interpolazione sarà

Q(r) = Q1*(1-r) + Q2*r

Come puoi vedere, quando R è 1/2, quindi a metà del bordo, il nostro interpolante si ridurrà a

Q(1/2,0,0) = (Q1 + Q2)/2

Logicamente, il valore medio sarà la media dei due endpoint. Si esegue l'interpolazione per ciascun canale di output in modo indipendente.

Q(1/2,0,0) = ([66, 51, 77] + [55, 66, 77])/2 = [60.5, 58.5, 77]

Funziona per recuperare gli endpoint? Certo che lo fa. Quando r = 0 o r = 1, puoi vedere che restituisce esattamente il corrispondente Q1 o Q2.

Ancora una volta, fai questa interpolazione lungo ciascuno dei quattro bordi rossi per un interpolante trilineare. Quindi fai altre due interpolazioni, forse lungo i bordi verdi dei quattro risultati che abbiamo ottenuto sopra. Infine, fai una singola più interpolazione lungo il bordo blu per ottenere l'interpolante trilineare. Ancora una volta, non importa quale ordine scegli gli assi dell'interpolazione. Il risultato sarà matematicamente lo stesso.

Stavi fermando a un'interpolazione bilineare, poi ci sono tre di queste interpolazioni lineari. Sì, è vero che un interpolante bilineare o un interpolante trilineare può anche essere fatto come una combinazione ponderata di tutti e 4 (o 8) angoli del rettangolo (o cubo). Che può essere lasciato al futuro.

/*
  resize an image using bilinear interpolation
*/
void bilerp(unsigned char *dest, int dwidth, int dheight, unsigned char *src, int swidth, int sheight)
{
  float a, b;
  float red, green, blue, alpha;
  float dx, dy;
  float rx, ry;
  int x, y;
  int index0, index1, index2, index3;

  dx = ((float) swidth)/dwidth;
  dy = ((float) sheight)/dheight;
  for(y=0, ry = 0;y<dheight-1;y++, ry += dy)
  {
    b = ry - (int) ry;
    for(x=0, rx = 0;x<dwidth-1;x++, rx += dx)
    {
      a = rx - (int) rx;
      index0 = (int)ry * swidth + (int) rx;
      index1 = index0 + 1;
      index2 = index0 + swidth;     
      index3 = index0 + swidth + 1;

      red = src[index0*4] * (1.0f-a)*(1.0f-b);
      green = src[index0*4+1] * (1.0f-a)*(1.0f-b);
      blue = src[index0*4+2] * (1.0f-a)*(1.0f-b);
      alpha = src[index0*4+3] * (1.0f-a)*(1.0f-b);
      red += src[index1*4] * (a)*(1.0f-b);
      green += src[index1*4+1] * (a)*(1.0f-b);
      blue += src[index1*4+2] * (a)*(1.0f-b);
      alpha += src[index1*4+3] * (a)*(1.0f-b);
      red += src[index2*4] * (1.0f-a)*(b);
      green += src[index2*4+1] * (1.0f-a)*(b);
      blue += src[index2*4+2] * (1.0f-a)*(b);
      alpha += src[index2*4+3] * (1.0f-a)*(b);
      red += src[index3*4] * (a)*(b);
      green += src[index3*4+1] * (a)*(b);
      blue += src[index3*4+2] * (a)*(b);
      alpha += src[index3*4+3] * (a)*(b);

      red = red < 0 ? 0 : red > 255 ? 255 : red;
      green = green < 0 ? 0 : green > 255 ? 255 : green;
      blue = blue < 0 ? 0 : blue > 255 ? 255 : blue;
      alpha = alpha < 0 ? 0 : alpha > 255 ? 255 : alpha;

      dest[(y*dwidth+x)*4] = (unsigned char) red;
      dest[(y*dwidth+x)*4+1] = (unsigned char) green;
      dest[(y*dwidth+x)*4+2] = (unsigned char) blue;
      dest[(y*dwidth+x)*4+3] = (unsigned char) alpha;
    }
    index0 = (int)ry * swidth + (int) rx;
    index1 = index0;
    index2 = index0 + swidth;     
    index3 = index0 + swidth;   

    red = src[index0*4] * (1.0f-a)*(1.0f-b);
    green = src[index0*4+1] * (1.0f-a)*(1.0f-b);
    blue = src[index0*4+2] * (1.0f-a)*(1.0f-b);
    alpha = src[index0*4+3] * (1.0f-a)*(1.0f-b);
    red += src[index1*4] * (a)*(1.0f-b);
    green += src[index1*4+1] * (a)*(1.0f-b);
    blue += src[index1*4+2] * (a)*(1.0f-b);
    alpha += src[index1*4+3] * (a)*(1.0f-b);
    red += src[index2*4] * (1.0f-a)*(b);
    green += src[index2*4+1] * (1.0f-a)*(b);
    blue += src[index2*4+2] * (1.0f-a)*(b);
    alpha += src[index2*4+3] * (1.0f-a)*(b);
    red += src[index3*4] * (a)*(b);
    green += src[index3*4+1] * (a)*(b);
    blue += src[index3*4+2] * (a)*(b);
    alpha += src[index3*4+3] * (a)*(b);

    red = red < 0 ? 0 : red > 255 ? 255 : red;
    green = green < 0 ? 0 : green > 255 ? 255 : green;
    blue = blue < 0 ? 0 : blue > 255 ? 255 : blue;
    alpha = alpha < 0 ? 0 : alpha > 255 ? 255 : alpha;

    dest[(y*dwidth+x)*4] = (unsigned char) red;
    dest[(y*dwidth+x)*4+1] = (unsigned char) green;
    dest[(y*dwidth+x)*4+2] = (unsigned char) blue;
    dest[(y*dwidth+x)*4+3] = (unsigned char) alpha;
  }
  index0 = (int)ry * swidth + (int) rx;
  index1 = index0;
  index2 = index0 + swidth;     
  index3 = index0 + swidth;   

  for(x=0, rx = 0;x<dwidth-1;x++, rx += dx)
  {
    a = rx - (int) rx;
    index0 = (int)ry * swidth + (int) rx;
    index1 = index0 + 1;
    index2 = index0;     
    index3 = index0;

    red = src[index0*4] * (1.0f-a)*(1.0f-b);
    green = src[index0*4+1] * (1.0f-a)*(1.0f-b);
    blue = src[index0*4+2] * (1.0f-a)*(1.0f-b);
    alpha = src[index0*4+3] * (1.0f-a)*(1.0f-b);
    red += src[index1*4] * (a)*(1.0f-b);
    green += src[index1*4+1] * (a)*(1.0f-b);
    blue += src[index1*4+2] * (a)*(1.0f-b);
    alpha += src[index1*4+3] * (a)*(1.0f-b);
    red += src[index2*4] * (1.0f-a)*(b);
    green += src[index2*4+1] * (1.0f-a)*(b);
    blue += src[index2*4+2] * (1.0f-a)*(b);
    alpha += src[index2*4+3] * (1.0f-a)*(b);
    red += src[index3*4] * (a)*(b);
    green += src[index3*4+1] * (a)*(b);
    blue += src[index3*4+2] * (a)*(b);
    alpha += src[index3*4+3] * (a)*(b);

    red = red < 0 ? 0 : red > 255 ? 255 : red;
    green = green < 0 ? 0 : green > 255 ? 255 : green;
    blue = blue < 0 ? 0 : blue > 255 ? 255 : blue;
    alpha = alpha < 0 ? 0 : alpha > 255 ? 255 : alpha;

    dest[(y*dwidth+x)*4] = (unsigned char) red;
    dest[(y*dwidth+x)*4+1] = (unsigned char) green;
    dest[(y*dwidth+x)*4+2] = (unsigned char) blue;
    dest[(y*dwidth+x)*4+3] = (unsigned char) alpha;
  }

   dest[(y*dwidth+x)*4] = src[((sheight-1)*swidth+swidth-1)*4];
   dest[(y*dwidth+x)*4+1] = src[((sheight-1)*swidth+swidth-1)*4+1];
   dest[(y*dwidth+x)*4+2] = src[((sheight-1)*swidth+swidth-1)*4+2];
   dest[(y*dwidth+x)*4+3] = src[((sheight-1)*swidth+swidth-1)*4+3];
}  

Codice mantenuto qui

https://github.com/malcolmmclean/babyxrc/blob/master/src/resize.c

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top