Considere os seguintes descritores de Textura: - QCCH [HuangQCCH2007] Extração: 1) Converte a imagem para cinza = O(n); 2) Para cada pixel (i,j), passa janela Nr: 2.1) Calcula Hr,Vr,Dr,Ar; 2.2) Acha média v(i,j)=Hi+V1+D1+A1/4; 2.3) Cada pixel possui um v(i,j); 2.3) Quantiza v(i,j) não uniformemente em 40 bins (T=40) = t(i,j) -- t=0,..,39; 3) Para cada t, calcula Ht(t) = O(n); === O(n)+O(n)+O(40n=Tn) = O(Tn) Distância: L1 = O(nb) Parece bom: Ganhou do SCH e foi parecido com Gabor (Precision); Muito mais rápido que Gabor e mais rápido que SCH (Extração); QCCH foi mais rápido para comparar; QCCH é orientation independent (invariante à rotação e translação) - HTD MPEG7 {ManjunathPBCSRC2000}, ~\cite{ManjunathGabor1996} Extração: Aplica S*K filtros de Gabor na imagem; São geradas S*K imgs filtradas -> O(Gabor); Acha a média e desvio padrão de cada imagem -> O(n)*S*K; === O(Gabor)+O(nSK) Distância: Diferença de cada elemento de média e desvio padrão normalizados sobre o desvio padrão deles sobre a base toda. === O(SK) + O(tamBase), S=qtd de escalas, K=qtde de orientações. DISTANCIA INVIAVEL POR CAUSA DA NORMALIZACAO, mas é um descritor classico da literatura. No MPEG7 foi chamado de HTD, mas é identico ao descritor conhecido como Gabor Wavelet. Segundo alguns estudos comparativos, ele é lento pra extrair. - LAS {TaoLAS2000} Extração: Mostra Gradient Indexing e Local Activity Spectrum (LAS). Gradient Indexing usa operadores como Sobel e calcula histograma dos gradientes (256 bins). LAS captura a atividade numa vizinhança; São obtidos 4 valores (g1, g2, g3, g4) para cada pixel. Gera um histograma de 4 bins para cada gi; Gera um histograma final com os 4 histogramas de gi num total de 256bins. Para CBIR, propõe: Dividir a imagem em blocos de S pixels cada (64x64 foi usado); Calcula o LAS de cada bloco; Clusteriza com k-means da seguinte forma: para cada pixel da borda de um bloco, soma as diferenças dos histogramas LAS dos blocos vizinhos (no max 8 blocos vizinhos). O pixel é agrupado no bloco que maximizar a soma = O(%n)*8*O(L1)*k iterações (do k-means). Calcula também um indicador de vizinhança dos blocos. === LAS:O(n) // Com segmentação: O(n)+O(n*nb*k) Distância: Distancia city-block = L1 = O(nb). // Para esquema com segmentação é pelo menos: O(m1*m2*(nb^2)), m1=qtde de blocos da consulta, m2=qtde de blocos da img da base; pelo menos, pois existe um outro componente no calculo da distancia que considera os indicadores de vizinhança e não são explicados no artigo A parte complicada da implementação acho que deve ser o agrupamento com o k-means. - Color Co-occurrence {KovalevColorCoOccurrence1998} Extração: 1)Quantiza RGB (6 valores para cada canal); 2)Calcula W (matriz de co-ocorrencia); 2.1)Percorre a imagem e, para cada par de pixels i,j com distancia max igual a d(=1), incrementa W(ci,cj,d) em 1, ci=indice da cor de i no espaço RGB quantizado; 2.2)Normaliza W pelo tamanho da imagem; 3)Usa função f(ci,cj,dij) para mapear de W para indices lineares (mesma funcao para todas as imagens); 4)Aplica thresholds min e max em w e, no final, tem-se uma lista com os valores não-nulos da matriz. === O(n), caso d=1 Distância: Soma as diferenças entre os w correspondentes e normaliza pela soma total dos w. === O(vectorSize) Foi rápido. Invariante à rotação, translação e reflexão. Independe do tamanho da img e consegue recuperar a partir de subpartes. Bom para heterogeneidade, rápido para extrair, mas FV é pouco compacto [PIOR CASO: todos os valores de W = 216(quantizacao RGB - 6 vals cada canal = 6*6*6=216)*216*2(d=0 e d=1)*2(indice e valor w) = 216*216*2*2=186624 valores = O(W). Com os thresholds nunca será a matriz toda.] - Matriz de co-ocorrência {HaralickCoOccurrence1973} Extração: Define-se distancia d (d=1); Quantiza níveis de cinza da imagem (Ng niveis); Qtd_direcoes = 4 (0, 45, 90, 135); Cria 4 matrizes para cada distancia com dimensoes NgxNg; Percorre a imagem e, para cada par de pixels (i,j) com distancia d entre eles, incrementa cada matriz na posicao (Ni,Nj), onde Ni=cor de i (Nj idem). == O(n). // Se extrair as informacoes das matrizes (coarseness, etc): o caso mais complexo é O(Ng^3), portanto: O(n) + O(Ng^3) Distância: usou classificacao de padroes É pouco compacto: Se salvar apenas as matrizes: 4 matrizes NgxNg para cada distancia = O(Ng^2 * d). // Se salvar as caracteristicas extraidas das matrizes: 4 (direcoes) * 14 (qtde maxima de caracteristicas) = 56 - LBP {OjalaLBP2002} Extração: Define um raio R e uma qtde de vizinhos P naquele raio (vizinhança circular) = Operador LBP_{P,R}; As coordenadas de um vizinho são dadas por (-Rsen(2*PI*p/P), Rcos(2*PI*p/P)); Se não cair exatamente no centro de um pixel, interpola (valores de cinza); Passa o operador LBP por toda a img: baseado na diferença entre brilho de gp menos brilho do centro gc, descobre U=qtde de transições 0/1 ou 1/0 no valor que representa a soma das diferenças de brilhos dos vizinhos em relacao ao centro [O(P)]; Se U<=2, LBP=soma das diferenças positivas; senão, LBP=P+1; Incrementa posição correspondente do histograma de (P+2) bins; Calcula Var_{P,R}=somatorio dos gp-media_dos_vizinhos [O(P)]; Incrementa histograma qdo Var eh usado (usa um histograma 2D que combina LBP e Var). === O(n*P), como P é fixo em 4, 8, 16 ou 24, pode-se afirmar que é O(n). Distância: L(S,M)=Somatorio, pra todo bin b, de: S_{b}*log(M_{b}), S=histograma da consulta, M=histograma da img da base === O(nb) Parece simples de calcular e implementar. Escolha um dos descritores acima para implementar. Considere as seguintes sugestões para a implementação: 1- Implemente o descritor em linguagem C. 2- Utilize a biblioteca de funções fornecida. Nesta biblioteca estão funções de leitura e gravação de imagens e estruturas de dados para a manipulação das imagens. Use as estruturas de dados conforme a biblioteca (Image, CImage, etc). 3- Você pode implementar o descritor usando uma estrutura de diretórios de compilação (com diretórios de fontes, includes, etc) ou então codificar tudo num único arquivo. 4- É importante que você implemente o algoritmo de extração e a função de distância do descritor como funções independentes. Elas devem seguir as especificações: void Extraction(char *img_path, char *fv_path); double Distance(char *fv1_path, char *fv2_path); A função Extraction é a responsável por extrair as características de uma imagem. O caminho dessa imagem no sistema de arquivos é o primeiro parâmetro da função. O segundo parâmetro é o caminho do arquivo que será gerado pela função. Este arquivo irá conter as características extraídas da imagem, ou seja, será o vetor de características. A função Distance é a responsável por comparar dois vetores de características. Ela recebe como parâmetro os caminhos dos dois arquivos de características a serem comparados. A função retorna um valor do tipo double que é a distância calculada. Obs.: caso a função de distância do descritor (proposta no artigo) gere um valor de similaridade ao invés de um valor de distância, faça a conversão para esse valor ser a distância e não a similaridade entre as imagens. Normalmente essa conversão é muito simples: a similaridade é inversamente proporcional à distância. 5- Verifique cuidadosamente se a implementação está correta. Para isso, sugere-se que você use a função de extração de características em mais de uma imagem diferente. Depois de testar a extração, teste a função de distância. Verifique se a distância calculada corresponde a uma distância coerente com as diferenças visuais entre as imagens. 6- Após testar bem seu descritor, entre no link abaixo e siga o procedimento de cadastro do descritor na ferramenta de testes: http://www.lis.ic.unicamp.br/~otavio/tests/ferramenta/cadastra_descritor.php