PUCPR- Pontifícia Universidade Católica Do Paraná
PPGIA- Programa de Pós-Graduação Em Informática Aplicada
PROF. DR. JACQUES FACON
LIMIARIZAÇÃO DE IMAGENS POR ENTROPIA BIDIMENSIONAL
Resumo: Este artigo apresenta a implementação do algoritmo de Limiarização de Imagens utilizando Entropia Bidimensional.
Palavras-chave: Limiarização, Entropia Bidimensional. 1. Introdução
A limiarização tradicional utiliza a segmentação (intensidade como separador) como base do processo a ser executado.
Um objeto pode ser entendido como uma região formada por pixels contínuos que tenham em comum uma faixa de intensidade; e a limiarização utiliza esta faixa de intensidade dos pixels para distinguí-los. O processo se baseia na análise do histograma da imagem, onde as faixas de intensidade correspondem às bandas do histograma.
Esta análise pode ser subdividida entre o histograma de objetos de um tipo sobre o fundo, que será chamado de histograma bidimensional, ou histograma de objetos de dois tipos sobre um fundo que será o histograma tridimensional.
Este é um processo muito veloz e em geral, é executado em apenas um passo. Podemos observar que em muitos casos este é sempre o primeiro método a ser testado e muitas vezes fornece bons resultados em situações ditas "impossíveis". Vale observar que a limiarização não funciona bem em imagens com iluminação não uniforme ou com baixo contraste entre as diversas regiões.
O processo de limiarização está subdividido entre o processo Manual e Automático. 1.1. Escolha do valores de Limiar
Como escolher os valores de limiar é uma questão básica na hora da limiarização.
Há inicialmente duas formas de executar esta tarefa, seja através da escolha manual, a qual não é precisa nem reprodutível, ou seja através de métodos automáticos, baseados na análise de propriedades do histograma estudado.
1.2. Métodos Automáticos
Os métodos automáticos utilizam os mínimos do histograma. Os mínimos correspondem às tonalidades intermediárias entre duas bandas.
Em geral, o operador do histograma escolhe a tonalidade próxima à banda de interesse e o programa busca os mínimos mais próximos, em ambos os lados da banda. Neste tipo de processo existem dois grandes problemas:
Os vales podem assumir valores muito baixos, ficando muito sensíveis a ruído.
2. Limiarização por Entropia Bidimensional
Na Limiarização por entropia bidimensional a separação entre o primeiro e o segundo planos é alcançada localizando o máximo de um critério de entropia bidimensional. Ambos o nível de cinza de cada pixel e o nível médio de cinza de seus vizinhos são usados para gerar uma superfície de entropia. O pico desta superfície determina o nível de cinza e o nível médio de cinza ao redor do limiar.
Além disso, um pixel pertence a um segmento se seu valor de nível de cinza satisfaz duas condições: a distribuição espacial do nível de cinza e a distribuição do nível de cinza. A frequência da ocorrência de cada par de níveis de cinza é calculada (ou seja, um histograma modificado). Isto irá desenhar uma superfície que deverá ter dois picos e um vale. Os picos correspondem ao primeiro e segundo planos. Eles podem ser separados pela escolha de um limiar que maximize a entropia nos dois grupos.
2.1. Método de limiarização
De acordo com [Abutaleb (1988)] , definindo m como o número de níveis de cinza, primeiro divide-se o nível de cinza em m valores e o nível de cinza médio também em m valores. A cada pixel, o nível de cinza médio da vizinhança é calculado. Desses dois valores um par é formado. Cada par pertence a uma célula bidimensional. O número total de células é m x m e o número total de pixels a serem testados é N x N (sendo N o número total de pixels da imagem). A frequência (fij) de um par (i, j) dividida pelo número total de pixels (N2) define a função de junção da probabilidade de massa:
2
N f
pij = ij ,
Assumindo que os componentes da diagonal têm valores próximos ao zero e que há dois grupos, A e B, que representam o primeiro e o segundo planos, com duas funções de probabilidade de massa diferentes (PMF). Se o limiar está localizado no par (s, t), então a área total abaixo de pij (i = 1, ..., s e j = 1, ..., t) deve ser um, já que pij nesta região representa a PMF condicional. Além disso, um processo de normalização é necessário e resulta em uma entropia modificada para o grupo A, H(A), definida como:
(
) (
)
= = − = s i t j ij st ij st P p P p A H 1 1 ln ) ( onde = = = s i t j ij st p P 1 1 Reescrevendo a equação acima definida, temos que:( ) ( ) ( )
( )
[
]
( )
st st st s i t j ij ij ij st st p p p P P H P P A H =− − = + = = ln ln ln ) 1 ( ) ( 1 1 onde( )
= = − = s i t j ij ij st p p H 1 1 ln Similarmente, uma entropia para o grupo B, H(B), é definida como( )
[
(
)
]
[
(
)
]
[
(
)
]
( ) ( )
[
(
)
]
(
st) (
mm st) (
st)
m s i m t j ij ij st st m s i m t j ij st ij st P H H P P p p P P p P p B H − − + − = − − − − = − − − = + = =+ + = =+ 1 1 ln 1 ln ln 1 1 1 ln 1 1 1 1 1A expressão para H(B) é válida quando pij ≈ 0 nas duas regiões definidas por i=s+1, ,m e j=1, ,t e por i=1, ,s e j=t+1, ,m. Esta suposição é razoável desde que em muitas situações as probabilidades de diagonais-off têm um valor desprezível. Esta suposição reduz o tempo computacional.
( )
(
) (
) (
)
(
)
[
st st]
st st(
mm st) (
st)
st st mm st st st st P H H P H P P P H H P P H P B H A H t s − − + + − = − − + − + + = + = 1 1 ln 1 1 ln ln ) ( ) ( ) , (ψ
O algoritmo então procura pelos valores de s e t que maximizam ψ (s, t), os quais representam onde o
valor de limiar está localizado.
2.2. Propriedades de ψψψψ (s, t) e o Algoritmo Computacional
Se assumirmos que há uma distribuição então s = t = 1 ou s = t = m. Neste caso temos ψ (1, 1) = ψ (m, m),
e estes são os pontos finais de ψ (s, t). Desde que ψ (s, t) é uma função contínua de valor real no intervalo definido por 1 < s < m e 1 < t < m, e desde que ψ (1, 1) = ψ (m, m), então há um par, 1 < s’ < m e 1 < t’ < m, tal que ψ (s’, t’) é um máximo ou um mínimo. Das propriedades da entropia bidimensional, os pontos finais são valores mínimos de ψ (s, t). Desta maneira ψ (s, t) atinge um máximo em s’ e t’.
O algoritmo para obter s’ e t’ é simples e iterativo. Os valores de s e t são modificados até que obtenhamos o máximo de ψ (s, t): max := 0 for (s = 1 to m) do begin for (t = 1 to m) do begin evaluate ψ (s,t); if ψ (s, t) > max then begin max := ψ (s, t); s’ := s, t’ := t; end; end; end; 2.3. Corrigindo o cálculo de Pst
Comparando com fórmulas de limiarização unidimensional, descobrimos que a fórmula correta é a seguinte: = = = = = = = = = s i t j ij s i t j ij s i t j ij st f N N f p P 1 1 2 1 1 2 1 1 1 2.4. Simplificação de ψψψ (s, t) ψ
Utilizando as equações originais, o cálculo de ψ (s, t) requer muitos cálculos. Para a implementação deste algoritmo, tornou-se necessária uma simplificação desses cálculos, demonstrada a seguir.
Substituindo p f N2 ij ij = em: = = = = = = = = = s i t j ij s i t j ij s i t j ij st p f N N f P 1 1 2 1 1 2 1 1 1
( )
=− =−(
( )
−( )
)
− = = = = = = = s i t j ij ij s i t j ij ij s i t j ij ij st f f N N N f f N p p H 1 1 2 2 1 1 2 2 1 1 ln ln 1 ln 1 lnDefinindo = = = i j ij st f MP 1 1 e
(
( )
( )
)
= = − − = i j ij ij st f f N MH 1 1 2 ln ln , temos que: 2 N MP P st st = e N2 MH H st st = . Substituindo em ψ (s, t):(
)
[
P
stP
st]
H
stP
st(
H
mmH
st) (
P
st)
t
s
,
)
=
ln
1
−
+
+
−
1
−
(
ψ
Como:(
)
[
]
(
)
ln[
(
)
]
2ln( ) ln ln 1 ln 1 ln 2 2 4 2 2 2 2 2 2 N MP N MP N MP N MP N MP N N MP N MP N MP P P st st st st st st st st st st − − = − = − = − = − st st st st st st MH MP MP N N MH P H = 2 2 =(
) (
)
(
mm st)
(
st)
st mm st st st mm MP N MH MH N MP N N MH MH P H H − − = + − = − − 2 2 2 2 1 Então:(
)
[
]
(
mm ss)
(
st)
st st st stMP
N
MH
MH
MP
MH
N
MP
N
MP
t
s
−
−
+
+
−
−
=
2 2 22
ln(
)
ln
)
,
(
ψ
3. ConclusõesCompreender o algoritmo não foi o mais difícil, e sim a escolha do valor de limiar. Não há explicação clara em [Abutaleb (1988)] de como encontrar o valor de limiar.
Em relação à implementação, há dificuldades no cálculo, como logaritmo neperiano e divisões por zero. No caso do logaritmo neperiano, quando o valor for menor ou igual a zero, o logaritmo é definido como zero. No caso de divisões por zero, a divisão é definida como zero.
De acordo com [Abutaleb (1988)] a limiarização pelo método de entropia bidimensional é uma alternativa à limiarização por entropia unidimensional, apresentando resultados superiores à segunda em relação à eficiência; mas em relação a tempo computacional a segunda exige menos que a primeira. De acordo com a implementação apresentada neste artigo e por meio da comparação de resultados, pode-se confirmar as conclusões obtidas por [Abutaleb (1988)].
4. Referências
[Abutaleb (1988)] Abutaleb, Ahmed S.; “Automatic Thresholding of Gray-Level Pictures Using Two Dimensional Entropy”; Computer Graphics & Image Processing, 47(1) - pp22-32, july 1989.
IMPLEMENTAÇÃO:
// Algoritmo de Limiarizacao por Entropia 2D (Bidimensional) BOOL CLimiar::LimiarEntropia2D()
{
const BYTE tab[8] = {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE}; unsigned long m1, m2;
unsigned long i, j; unsigned long t, s, g; unsigned long indice; unsigned int col, lin;
double SPst[256], SHst[256]; double N2,lnN2; double MPst, MHst, MHmm; double xmedia; double Max; double resultado; double aux1, aux2; unsigned long dado;
double frequencia[256][256]; HGLOBAL hmedia; double FAR *media; BYTE Limiar_s,Limiar_t; BYTE *bpTempIn,*bpTempOut;
DWORD dwWidthBytesIn,dwWidthBytesOut; if ( !(VerifyConsistentIn() && VerifyConsistentOut()) ) return FALSE; CopyImageInOut(); ClockStart(); Histograma(); bpTempIn = piRW_ImgIn->GetImageBits(); bpTempOut = piRW_ImgOut->GetImageBits(); dwWidthBytesIn = piRW_ImgIn ->GetImageWidthBytes(); dwWidthBytesOut = piRW_ImgOut->GetImageWidthBytes(); hmedia = GlobalAlloc(GPTR, m_Height*m_Width*sizeof(double)); media = (double FAR*) GlobalLock(hmedia);
N2 = (m_Width * m_Height) * (m_Width * m_Height); lnN2 = log(N2);
// inicialização de vetores com 0
// inicializar histograma bidimensional com 0 for (i = 0; i < 256; i++)
{
SHst[i] = 0.0;
for (j = 0; j < 256; j++) frequencia[i][j] = 0.0; }
// inicializar media da imagem com 0 for (i = 0; i < m_Height; i++) {
for (j = 0; j < m_Width; j++) media[i*m_Width + j] = 0.0; }
// cálculo da frequência do bitmap e de sua média {
xmedia = 0.0;
// cálculo da frequência do bitmap, menos os pixels das bordas for(lin = 1; lin < m_Height-1; lin++)
{
indice = lin * dwWidthBytesIn;
// cálculo da frequência bidimensional da primeira coluna do bitmap
xmedia = bpTempIn[indice + 1] + bpTempIn[indice ] + bpTempIn[indice + 2];
xmedia += bpTempIn[indice - dwWidthBytesIn + 1] + bpTempIn[indice - dwWidthBytesIn] + bpTempIn[indice - dwWidthBytesIn + 2];
xmedia += bpTempIn[indice + dwWidthBytesIn + 1] + bpTempIn[indice + dwWidthBytesIn] + bpTempIn[indice + dwWidthBytesIn + 2];
xmedia /= 9;
frequencia[int(bpTempIn[indice-dwWidthBytesIn])][int(xmedia)]++; media[lin * m_Width] = xmedia;
col = 1; do {
// cálculo da frequência bidimensional da parte interna do bitmap frequencia[int(bpTempIn[indice + col])][int(xmedia)]++; media[lin * m_Width + col] = xmedia;
col++;
// cálculo da média
xmedia = bpTempIn[indice + col] + bpTempIn[indice + col - 1] + bpTempIn[indice + col + 1];
xmedia += bpTempIn[indice - dwWidthBytesIn + col] + bpTempIn[indice - dwWidthBytesIn + col - 1] + bpTempIn[indice - dwWidthBytesIn + col + 1];
xmedia += bpTempIn[indice + dwWidthBytesIn + col] + bpTempIn[indice + dwWidthBytesIn + col - 1] + bpTempIn[indice + dwWidthBytesIn + col + 1];
xmedia /= 9;
} while(col < m_Width-2);
frequencia[int(bpTempIn[indice + col])][int(xmedia)]++; media[lin * m_Width + col] = xmedia;
// cálculo da frequência bidimensional da última coluna do bitmap frequencia[int(bpTempIn[indice + m_Width - 1])][int(xmedia)]++; media[(lin+1) * m_Width - 1] = xmedia;
}
// cálculo da frequência bidimensional da primeira e da última linhas do bitmap for(indice = (m_Height-1)*dwWidthBytesIn, col = 0; col < m_Width; col++) {
media[col] = media[m_Width + col];
xmedia = (m_Height-1) * m_Width + col;
media[int(xmedia)] = media[int(xmedia)-m_Width];
frequencia[int(bpTempIn[indice+col])][int(media[int(xmedia)])]++; }
}
// busca do maximo = limiar Max = 0.0; Limiar_s = 0; Limiar_t = 0; resultado = 0.0; aux1 = 0.0; aux2 = 0.0; // cálculo de MHmm MHmm = 0; for(m1 = 0; m1 < 256; m1++) { for(m2 = 0; m2 < 256; m2++) { aux1 = frequencia[m1][+m2]; if (aux1 != 0) MHmm -= (aux1 * (log(aux1) - lnN2)); } }
// cálculo para obter o máximo da função de limiar for(s = 0; s < 256; s++) { for(t = 0; t < 256; t++) { // cálculo de MPst e MHst aux1 = frequencia[s][t]; if (aux1 != 0) { for(g=t; g < 256; g++) SPst[g]+= aux1;
aux2 = - aux1 * (log(aux1) - lnN2); for(g=t; g < 256; g++) SHst[g]+= aux2; } MPst = SPst[t]; MHst = SHst[t]; // início do cálculo aux1 = MPst * (N2 - MPst); resultado = 0.0; if (aux1 > 0) resultado = log(aux1); resultado -= (2 * lnN2); if (MPst != 0) resultado += (MHst / MPst);
// anterior + ((MHst - MHmm)/(N2 + MPst)) if ( (N2 - MPst) != 0) resultado += (MHmm - MHst)/(N2 - MPst); if ( (resultado > Max) ) { Max = resultado; Limiar_s = (BYTE)s; Limiar_t = (BYTE)t; } } } SetLimiar_S((BYTE)Limiar_s); SetLimiar_T((BYTE)Limiar_t); // Aplicação do limiar na imagem
for(lin = 0; lin < m_Height; lin++,bpTempIn+=dwWidthBytesIn,bpTempOut+=dwWidthBytesOut) {
for(col = 0; col < m_Width; col++) {
unsigned long idx = (col / 8); dado = bpTempIn[col];
bpTempOut[idx] &= tab[col % 8];
if ( (dado < Limiar_s) && (media[lin * m_Width + col] < Limiar_t) ) bpTempOut[idx ] |= ( (FALSE) << (7 - (col % 8)) ); else
bpTempOut[idx ] |= ( (TRUE ) << (7 - (col % 8)) ); }
}
GlobalUnlock(hmedia); GlobalFree(hmedia);
ClockFinish("Limiarizacao por Entropia 2D (Bidimensional)"); return TRUE;