# Last edited on 2004-02-01 19:11:26 by stolfi Como utilizar os gabaritos de iluminacao Resumo Os "gabaritos de iluminação" são as esferas brancas. A aparência de um gabarito na imagem permite determinar a distribuição direcional da luz naquela região do palco. Por interpolação dos três gabaritos é possível então estimar a distribuição da luz em qualquer outro ponto. Uma vez conhecidas as distribuições direcionais da luz em três imagens A, B, C de um fragmento -- na mesma posição, tiradas do mesmo ponto de vista mas com luzes diferentes --- é possível determinar a inclinação em cada ponto da superfície do mesmo, e sua cor intrínseca. Esta análise deve ser feita separadamente para cada canal (Red,Grn,Blu) da imagem. Provavelmente os canais Red e Grn darão melhores resultados que o canal Blu, pois este tem mais ruído nas imagens da Mavica CD-300. Os resultados podem ser combinados no final para dar mais precisão. Localizando o gabarito O primeiro passo na análise é localizar as imagens dos gabaritos, com a maior precisão possível. Para as imagens em questão, podemos supor que o gabarito é esférico, e que sua projeção na imagem é circular. Isso não é rigorosamente correto, pois a imagem de uma esfera em perspectiva é na verdade uma elipse, e além disso gabarito não é uma esfera perfeita; mas, no nosso caso, estes desvios não devem fazer muita diferença. Portanto a localização de cada gabarito é descrita por um centro, cujos índices serão denotados abaixo por [iCtr,jCtr], e um raio rGab. Estes parâmetros devem ser medidos manualmente e verificados traçando-se o círculo sobre a imagem. É bom supor que eles podem ser fracionários (vide mais adiante). Como as imagens A,B,C devem estar perfeitamente alinhadas, estes parâmetros devem ser os mesmos para as três imagens. Por outro lado, gabaritos diferentes na mesma imagem podem ter raios um pouco diferentes. Descrevendo as distribuições de luz Esta seção deve ser repetida separadamente para cada canal (Red, Grn, ou Blu) da imagem colorida. Portanto usaremos A[i,j] para indicar a intensidade do pixel [i,j] nesse canal (ou seja, A[i,j].Red, A[i,j].Grn, ou A[i,j].Blu, conforme o caso). Idem para B[i,j] e C[i,j]. A intensidade A[i,j] deve ser um número entre 0 e 1. É importante que este número seja proporcional à intensidade física da luz emitida por esse ponto da cena. Ou seja, a imagem A deve ter sido corrigida para uma escala linear de intensidade (gama = 1), invertendo-se a função de transferência da câmera determinada na etapa anterior do projeto. A distribuição direcional da luz, numa determinada região do palco, é uma funçao f(d) que, para cada direção d (vetor unitário do R^3), diz qual a intensidade efetiva da luz que incidiria sobre uma superfíce perpendicular a esse vetor. "Intensidade efetiva" é a cor aparente que essa superfície teria se fosse pintada com tinta branca fosca. Portanto, nas vizinhanças de um gabarito, f(d) é simplesmente a cor aparente do gabarito no ponto do mesmo cuja direção normal é d. Para facilitar as contas geométricas, vamos usar um sistema de coordenadas centrado no próprio gabarito. Nesse sistema, o pixel com índices [i,j] tem coordenadas X = (j - jCtr), Y = (iCtr - i), e portanto Z = sqrt(rGab^2 - X^2 - Y^2). A direção d normal à superfície do gabarito, nesse ponto, será então d = (X/rGab, Y/rGab, Z/rGab). Reciprocamente, o ponto do gabarito com normal d = (dx, dy, dz) tem coordenadas (X,Y,Z) = (rGab*dx, rGab*dy, rGab*dz) neste sistema, e corresponde ao pixel da imagem com índices [iCtr + X, jCtr - Y]. O próximo passo então é gerar uma lista fixa de direções d, e anotar a cor aparente do ponto do gabarito que tem normal d. As direções podem ser geradas pela malha para kr = 0 to M-1 N = floor(Pi*kr) + 1 para kt = 0 to N-1 r = kr/M t = 2*Pi*kt/N dx = r*cos(t) dy = r*sin(t) dz = sqrt(1 - dx*dx - dy*dy) X = rGab*dx Y = rGab*dy Z = rGab*dz i = iCtr + X j = jCtr - Y Acredito que M = 30 é uma resolução adequada. Para cada uma dessas direções, calculamos o pixel correspondente [i,j] na imagem A, como descrito acima, e obtemos as distribuições de luz a(d) = A[i,j], b(d) = B[i,j], e c(d) = C[i,j]. Note que os valores de i e j são fracionários, portanto A[i,j] deve ser obtido por interpolação linear dos 4 pixels mais próximos. O resultado é uma tabela dx dy dz a(d) b(d) c(d) que dá, as iluminações efetivas nas três imagens, para cada direção normal d. Usando as distribuições de luz Seja agora um ponto [i,j] qualquer de um fragmento, cujas cores nas três imagens são cA = A[i,j], cB = B[i,j], cC = C[i,j]. Nosso objetivo é determinar a direção D[i,j] normal à superfície do fragmento nesse ponto. Podemos supor que o fragmento é fosco mas tem, nesse ponto, uma cor própria S[i,j]. Esse número é a cor que o ponto [i,j] do fragmento teria se fosse iluminado com luz de intensidade efetiva 1. Quando ele é iluminado com luz de intensidade efetiva g, sua cor aparente será g*S[i,j]. Na imagem A, o ponto está iluminado com luz de intensidade efetiva a(D[i,j]), e analogamente para as outras duas imagens. Portanto temos as equações cA = a(D[i,j]) * S[i,j] cB = b(D[i,j]) * S[i,j] [1] cC = c(D[i,j]) * S[i,j] Ou seja, o vetor (cA, cB, cC) deve ser um múltiplo do vetor (a(D[i,j]), b(D[i,j]), c(D[i,j]). Portanto, para encontrar a normal desconhecida D[i,j], basta procurar na tabela acima uma linha dx dy dz a(d) b(d) c(d) tal que o vetor (a(d), b(d), c(d)) seja o mais próximo possível de um múltiplo de (cA, cB, cC). Para isso, basta calcular a distância K(d) entre os dois vetores normalizados (cA, cB, cC) u = ----------------------------- [2] sqrt(cA^2 + cB^2 + cC^2) (a(d), b(d), c(d)) v = ----------------------------------- [3] sqrt(a(d)^2 + b(d)^2 + c(d)^2) K(d) = dist(u,v) [4] e escolher a direção d que dá o valor mínimo para K(d). Esta é a direção normal estimada para o ponto [i,j] da imagem que é mais consistente com as diferenças observadas entre as cores A[i,j], B[i,j] e C[i,j]. Uma vez escolhida a normal d = D[i,j], obtemos de lambuja a cor própria S[i,j] do ponto P. Segundo as equações [1], esta é a relação entre os comprimentos dos dois vetores (cA, cB, cC) e (a(D[i,j]), b(D[i,j]), c(D[i,j]), ou seja sqrt(cA^2 + cB^2 + cC^2) S[i,j] = ------------------------------------ [5] sqrt(a(d)^2 + b(d)^2 + c(d)^2) A imagem de inclinação Ao repetirmos a análise acima para os três canais de cor (Red, Grn, Blu), obteremos três estimativas DRed[i,j], DGrn[i,j] e DBlu[i,j] para a normal, cada qual com 3 componentes X,Y,Z; e três valores S[i,j].Red, S[i,j].Grn, S[i,j].Blu para a cor própria, cada qual um número real. Em teoria, a normal deveria ser a mesma para os três canais, isto é DRed[i,j] = DGrn[i,j] = DBlu[i,j]. Na prática estes vetores podem ser diferentes, devido a ruído nos valores de cA, cB, cC, a(d), b(d) e c(d). Se isso acontecer, podemos simplesmente definir D[i,j] como sendo a normal obtida com o canal mais confiável (provavelmente DGrn, talvez DRed). Ou, então, podemos tirar algum tipo de média ponderada das três normais: D[i,j] = dir(wRed*DRed[i,j] + wGrn*DGrn[i,j] + wBlu*DBlu[i,j]) onde wRed, wGrn e wBlu são pesos proporcionais à confiabilidade de cada canal, e dir(x) = x/|x| denota a direção do vetor x. De qualquer forma, podemos escrever as três componentes X,Y,Z do vetor D[i,j] como os três canais Red,Grn,Blu de uma imagem colorida, a /imagem de inclinação da cena/. (Na gravação, lembrar que as coordenadas de D[i,j] variam entre -1 e +1.) Nesta imagem, as partes da cena voltadas diretamente para a câmera (d = (0,0,+1)) devem ser azuis. As partes inclinadas para Leste (d=(+1,0,0)) terão tons vermelhos, as inclinadas para Oeste (d=(-1,0,0)) terão tons de ciano. As partes inclinadas para Norte serão verdes, as inclinadas para o Sul serão magenta. Em particular, o chão do palco deve ter uma cor quase uniforme, próxima do azul. A correção dos cálculos pode ser conferida observando-se as cores dos gabaritos nesta imagem. As cores acima devem ocorrer, respectivamente, no centro e nos pontos Leste, Oeste, Norte e Sul do círculo correspondente. A imagem de cor própria Os valores de S[i,j] calculados para cada canal, S[i,j].Red, S[i,j].Grn, S[i,j].Blu podem ser gravados como uma outra imagem colorida, a /imagem de cor própria/ da cena. Nesta imagem, cada pixel S[i,j] fornece a cor intrínseca daquele ponto da cena, eliminado o efeito da iluminação. Portanto, o fundo e os gabaritos devem ter cor uniform próxima do branco (sem sombras), as pintas devem ter cor cinza, e cada fragmento deve ter uma cor mais ou menos uniforme, também sem sombras. Complicação: defeitos dos gabaritos Os gabaritos não são lisos nem esféricos. Como o que importa é a direção normal, mesmo um calombo ou buraco raso (< 1mm) pode causar um erro grande (> 10 graus) entre a direção normal real num ponto [i,j] e a direção normal d prevista pelas fórmulas acima. Além disso, a pintura tem defeitos pontuais, sujeirinhas e arranhões -- ou seja a suposição de "branco fosco" da teoria não é exatamente verdadeira. Para contornar estes problemas, é melhor trabalhar com uma versão suavizada e filtrada da imagem. Para construir a tabela de iluminação, use a imagem gerada por convert f0a.jpg -geometry '192' -median 1 f0a-mm.ppm Lembre-se de multiplicar iCtr, jCtr e rGab pela mesma escala (192/2048). Uma vez obtida a tabela, os demais cálculos podem ser efetuados numa versão maior da imagem, por exemplo a obtida com convert f0a.jpg -geometry '512' f0a-nn.ppm Note que a tabela de iluminação e os demais cálculos não dependem dos parâmetros iCtr, jCtr e rGab. Complicação: variação da iluminação sobre a cena A distribuição da luz varia de ponto para ponto da cena, portanto os cálculos acima valem apenas nas vizinhanças do gabarito que foi usado para construir a tabela. Para obter resultados válidos para a cena toda, precisamos fabricar um "gabarito virtual" para cada ponto [i,j] da imagem. Ou seja, precisamos estimar a intensidade de iluminação a(d) nesse ponto da imagem A, para cada valor de d, combinando os valores de a0(d), a1(d), a2(d) dados pelas tabelas dos três gabaritos. Idem para as outras imagens b(d) e c(d). Para isso podemos usar interpolação linear das tabelas. Sejam [iCtr0,jCtr0], [iCtr1,jCtr1], [iCtr2,jCtr2] os centros dos três gabaritos. Resolvendo um sistema linear 3x3, encontramos as /coordenadas baricêntricas/ do pixel [i,j] relativo a esses três pontos: ou seja, três números alfa0, alfa1, alfa2 tais que alfa0 + alfa1 + alfa2 = 1 alfa0*iCtr0 + alfa1*iCtr1 + alfa2*iCtr2 = i alfa0*jCtr0 + alfa1*jCtr1 + alfa2*jCtr2 = j Isso significa que o ponto [i,j] é uma mistura dos três centros, com pesos alfa0, alfa1, alfa2. Portanto nosso "gabarito virtual" pode ser uma mistura dos três gabaritos usando os mesmos pesos. Ou seja, para cada direção d, calculamos a(d) = alfa0*a0(d) + alfa1*a1(d) + alfa2*a2(d) b(d) = alfa0*b0(d) + alfa1*b1(d) + alfa2*b2(d) c(d) = alfa0*c0(d) + alfa1*c1(d) + alfa2*c2(d) Esta é apenas uma aproximação linear para uma função que é sabidametne não-linear, portanto não será exata. Mas espera-se que seja suficiente para o gasto. Uma vez que cada imagem foi obtida com uma única lâmpada numa sala escura, em teoria é possível determinar a direção e distância dessa lâmpada a partir das imagens dos três gabaritos. Comesses dados, seria possível calcular a distribuição de luz em qualquer ponto da imagem. Entretanto, na prática há complicações: a lâmpada não é apenas um ponto, o feixe que ela projeta tem uma forma complicada, etc. etc. Portanto é melhor deixar essa idéia para mais tarde. Complicação: sombras As luminárias usadas têm umas alças de metal que servem para ajustar a posição da lâmpada sem queimar os dedos. Em algumas das imagens, a sombra dessa alça caiu sobre a cena, deixando uma faixa mais escura em forma de trapézio. Se isso não for levado em conta, as inclinações nessa parte da cena ficarão incorretas (pois as três iluminações interpoladas a(d), b(d) e c(d) serão afetadas de maneira diferente, e portanto as direções dos vetores (a(d), b(d), c(d)) estarão incorreta naquela região. Na imagem de inclinação, vai parecer que a cena toda tem um degrau nessa região. Em teoria, é possível detectar e corrigir este defeito examinando a cor do papel da quadrícula. Mas isto seria bastante tarabalhoso, portanto, por enquanto, fica apenas o aviso. Este problema também ocorre quando a sombra de um fragmento ou gabarito cai sobre outro. As inclinações calculadas nessa parte da cena estarão todas erradas.